Skip to content
Taskvisor 0.9source v0.9.0

Choose task behavior ​

Choose behavior after each attempt ​

TaskSpec selects what happens after success or a retryable failure:

ConstructorAfter successAfter a retryable failure
onceStop.Stop.
restartableStop.Retry if the retry limit allows.
periodicRepeat after the interval; see periodic timing for zero.Retry through failure backoff if the retry limit allows.
from_defaultsUse TaskDefaults.Use TaskDefaults.

One task ID runs attempts sequentially. Two attempts for that ID never overlap. These constructors choose a RestartPolicy, or inherit it from TaskDefaults. An explicit with_restart call can change that choice.

Interpret attempt results ​

Each attempt returns Ok(()) or a TaskError:

Attempt resultMeaning
Ok(())Success. The restart policy decides whether another attempt follows.
TaskError::FailRetryable failure.
TaskError::TimeoutRetryable timeout reported by task code.
TaskError::FatalPermanent failure; stop without retry.
TaskError::CanceledCooperative cancellation; stop without retry.
Configured timeoutDrop the attempt future; report a retryable timeout if cleanup succeeds.

A returned TaskError::Timeout produces the ordinary AttemptFailed event. A configured attempt deadline drops the attempt future. If cleanup succeeds, it produces AttemptTimedOut and a retryable timeout. Both timeout failures follow the restart policy and retry limit. If dropping the attempt future panics, Taskvisor instead produces AttemptFailed and ends with a final Panicked outcome without retrying.

With panic unwinding enabled, a panic while creating or polling the attempt future becomes a retryable failure. A panic while destroying attempt-owned data inside the actor can instead produce a final Panicked outcome. Later deferred destruction of the retained task object cannot change an outcome already delivered. panic = "abort" cannot be caught.

See Final outcomes and lifecycle events for final results, and Cancellation and shutdown for timeout limits.

Make repeated attempts safe ​

A restartable task can run again after a retryable failure, timeout, or caught task panic. Taskvisor cannot know whether an external system committed a side effect before the failure. Return a retryable result only when repeating the attempt is acceptable.

Application decisionAttempt result
Temporary failure and repeating the operation is safeTaskError::Fail
Task-reported deadline and repeating the operation is safeTaskError::Timeout
The application classifies the failure as permanentTaskError::Fatal
Cancellation was observed and cooperative cleanup finishedTaskError::Canceled
The attempt completed its required workOk(())

For external side effects, use an application-owned idempotency key, transaction, reconciliation read, deduplication record, or acknowledgement protocol as appropriate. Taskvisor manages retries. It does not provide rollback, durable execution, or exactly-once execution.

Bound failure retries ​

A retry limit set with with_max_retries counts retries after the first failed attempt. A limit of three therefore allows at most four consecutive failed attempts. A successful attempt resets the failure streak.

Configure retry timing ​

BackoffPolicy sets the delay after retryable failures. It does not set the delay after success.

rust
use std::num::NonZeroU32;
use std::time::Duration;
use taskvisor::{BackoffPolicy, JitterPolicy, TaskRef, TaskSpec};

fn supervised(name: &str, task: TaskRef) -> TaskSpec {
    TaskSpec::restartable(name, task)
        .with_backoff(
            BackoffPolicy::exponential(Duration::from_millis(200))
                .with_max(Duration::from_secs(30))
                .with_jitter(JitterPolicy::Equal),
        )
        .with_timeout(Duration::from_secs(10))
        .with_max_retries(NonZeroU32::new(3).unwrap())
}

Equal jitter chooses a delay between half of the current base delay and the full base delay. This spreads retries that would otherwise happen together. Per-task settings override values inherited from TaskDefaults; see configuration inheritance.

Understand periodic timing ​

A non-zero periodic interval starts after a successful attempt completes. It is fixed-delay scheduling, not a wall-clock or cron schedule. Taskvisor also keeps successive attempt starts at least one millisecond apart. When the attempt runtime plus the configured interval is shorter, Taskvisor extends the wait to reach that spacing. For example, a 500µs interval remains configured, but a sufficiently fast task starts no more often than once per millisecond. Passing Duration::ZERO removes the configured interval; the one-millisecond start-spacing guard still applies.

See periodic.rs, restart_policies.rs, and configuration.rs.

Source: attempt loop, one-attempt execution, and backoff calculation.

Open-source task execution components.