Skip to content
Taskvisor 0.9source v0.9.0

Configure Taskvisor ​

Configure each concern ​

Each configuration type has one role:

TypeControls
SupervisorConfigRuntime limits and shutdown.
TaskDefaultsTask settings inherited at registration.
TaskSpecSettings for one task.
ControllerConfigKeyed-admission limits.
Subscribe::queue_capacityOne subscriber's event queue.

Runtime settings stay fixed after the supervisor is built.

Set runtime and task defaults ​

rust
use std::num::{NonZeroU32, NonZeroUsize};
use std::sync::Arc;
use std::time::Duration;
use taskvisor::{Supervisor, SupervisorConfig, TaskDefaults};

fn configured_supervisor() -> Arc<Supervisor> {
    let runtime = SupervisorConfig::default()
        .with_grace(Duration::from_secs(30))
        .with_subscriber_shutdown_timeout(Duration::from_secs(5))
        .with_max_concurrent(NonZeroUsize::new(16))
        .with_ownership_capacity(NonZeroUsize::new(4096));

    let tasks = TaskDefaults::default()
        .with_timeout(Duration::from_secs(20))
        .with_max_retries(NonZeroU32::new(5).unwrap());

    Supervisor::builder(runtime)
        .with_task_defaults(tasks)
        .build()
}

The values in this example show where each setting belongs. They are not capacity recommendations for every application.

Inherit or override task settings ​

At registration, Taskvisor fills inherited settings from TaskDefaults. The TaskSpec constructor decides which fields inherit:

ConstructorRestart policyOther settings
from_defaultsInherited.Backoff, timeout, and retry limit are inherited.
once, restartable, periodicChosen by the constructor.Backoff, timeout, and retry limit are inherited.
newPassed explicitly.Backoff and timeout are explicit; retries start as unlimited.

A later with_* call overrides that field, including an inherited limit:

To disable retries, use TaskSpec::once or RestartPolicy::Never. See Choose task behavior for the restart policies.

Know the defaults ​

Main defaults:

SettingDefault
Graceful task shutdown60 seconds.
Subscriber drain5 seconds, shared by all subscriber queues.
Concurrent task attemptsUnlimited.
Registered-task limit1024.
Ownership capacity1024 per supervisor across accepted tasks and subscribers.
Event bus capacity1024.
Subscriber queue capacity1024 per subscriber; override through queue_capacity.
Registry command capacity1024.
Restart policyOn retryable failure.
Failure backoff200 ms initial base, capped at 30 s, with equal jitter; the first delay is 100–200 ms.
Attempt timeoutNone.
Failure retry limitUnlimited.

Bound different resources ​

Three limits answer different questions:

LimitWhat it bounds
max_concurrentAttempts physically running at the same time.
max_registered_tasksRegistered and removing tasks through terminal cleanup; force-aborted work can remain charged longer.
ownership_capacityAccepted task and subscriber values still owned through physical cleanup.

SupervisorConfig::with_ownership_capacity(None) removes the ownership count bound. Cleanup still uses a bounded worker set, but retained values and cleanup backlog can then grow without a count limit. Use Supervisor::ownership_snapshot or SupervisorHandle::ownership_snapshot to inspect configured and effective limits, available units, waiting requests, and deferred cleanup.

During cleanup handoff, one task can temporarily consume two max_registered_tasks units.

Choose values for an application ​

Choose limits from the application's needs:

  1. Decide which failures may repeat and whether retries need a finite limit.
  2. Choose an attempt timeout only for operations that are safe to stop by dropping their future.
  3. Bound concurrent attempts and registered tasks to fit the work and its dependencies.
  4. Keep a finite ownership limit unless the application accepts an unbounded number of retained values and cleanup batches.
  5. Choose task grace and subscriber drain deadlines that match the application's shutdown owner.
  6. When using keyed admission, configure controller queues and tracked-slot limits separately.
  7. Observe direct outcomes, best-effort events, and runtime snapshots at their documented boundaries.

Observe ownership pressure ​

OwnershipSnapshot separates admission pressure from deferred cleanup:

rust
use taskvisor::SupervisorHandle;

fn report_ownership(handle: &SupervisorHandle) {
    let state = handle.ownership_snapshot();

    println!(
        "in_use={:?} available={:?} waiters={} cleanup_queued={} \
         cleanup_running={} retired={:?} admission_open={}",
        state.in_use(),
        state.available,
        state.waiters,
        state.cleanup_queued,
        state.cleanup_running,
        state.retired(),
        state.admission_open,
    );
}

waiters counts ownership requests waiting for capacity. cleanup_queued and cleanup_running count batches waiting for or running on destructor workers. retired() reports permanent loss from a finite ownership capacity after destructor failure. An available count of zero does not by itself mean the next waiting request will fail. Another owned value may release its unit. Capacity fields are None when ownership admission is unlimited. The snapshot combines separate reads and can become stale immediately.

Checked try_with_* methods accept raw integers and return ConfigError for invalid values.

Source: runtime settings, task defaults, task-setting resolution, and ownership snapshot.

Open-source task execution components.