[dependencies]
taskvisor = "0.0"[dependencies]
taskvisor = { version = "0.0", features = ["controller", "logging"] }See crates.io for the latest version.
Helps you build resilient, event-driven async systems in Rust.
It's a small orchestrator that watches over your background tasks restarting, tracking, and signaling what happens.
┌────────────┐ runs & restarts ┌──────────────┐
│ Tasks │ ◄───────────────────── │ Supervisor │
└────────────┘ └──────┬───────┘
▼
emits events
▼
┌──────────────┐
│ Subscribers │ ◄─ your listeners
└──────────────┘
Use it for long-lived jobs, controllers, or background workers that must stay alive, observable, and restart safely.
Async systems grow fast: tasks, loops, background jobs, controllers.
Eventually you need structure: who runs what, what happens on failure, how to restart safely, and how to observe it all.
Taskvisor provides that structure: a small, event-driven supervision layer that keeps async work supervised and transparent.
Runs forever, restarts automatically on each completion, and emits lifecycle events:
use tokio_util::sync::CancellationToken;
use taskvisor::{
Supervisor, TaskFn, TaskSpec, Config, TaskRef,
TaskError, RestartPolicy, BackoffPolicy,
};
#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let sup = Supervisor::new(Config::default(), Vec::new());
let ping: TaskRef = TaskFn::arc("ping", |ctx: CancellationToken| async move {
if ctx.is_cancelled() {
return Err(TaskError::Canceled);
}
println!("[ping] pong");
Ok(())
});
let spec = TaskSpec::new(
ping,
RestartPolicy::Always,
BackoffPolicy::default(),
None,
);
sup.run(vec![spec]).await?;
Ok(())
}cargo run --example {{ example_name }} --features {{ features }}| Example | Description | Features |
|---|---|---|
| subscriber.rs | Custom subscriber reacting to events | - |
| control.rs | Tasks add/remove/cancel while supervisor is running | - |
| controller.rs | Tasks example with additional admissions | controller |
- Supervisor manage async tasks, tracks lifecycle, handles requests, and drives graceful shutdown.
- Registry coordinates task actors, spawning and removing them in response to runtime events.
- TaskActor per-task execution loop applying restart, backoff, and timeout policies for each run.
- TaskSpec declarative task definition combining restart behavior, backoff strategy, and optional timeout.
- TaskFn lightweight adapter turning async closures into supervised tasks.
- RestartPolicy / BackoffPolicy configurable restart control and retry delay strategies.
- Bus broadcast channel delivering structured runtime events to subscribers and the controller.
- Event typed event model.
- Subscribe extension point for custom event consumers, each with its own bounded queue and worker.
- Controller (feature =
controller) slot-based orchestrator with admissions:Queue,Replace, andDropIfRunning.
TaskFn (your async code with CancellationToken)
├─► wrapped in TaskSpec
│ (RestartPolicy + BackoffPolicy + timeout)
└─► passed to Supervisor
├─► spawns Registry
│ └─► creates TaskActor per task
│ └─► runs TaskSpec in loop
│ └─► publishes Event to Bus
└─► Bus distributes events to:
└─► Subscribe implementations (your metrics/logs)
Optional Controller (feature-gated):
ControllerSpec ─► Controller ─► Supervisor.add_task(TaskSpec)
(admission policies: Queue/Replace/DropIfRunning)
| Feature | Description | Use when |
|---|---|---|
controller |
Enables slot-based orchestration (Controller, ControllerSpec, etc.) |
Need admission control |
logging |
Enables the built-in LogWriter, demo logger |
Debugging (Demo) |
We're open to any new ideas and contributions.
Found a bug? Have an idea? We welcome pull requests and issues.