🤖 task-supervisor

The task-supervisor
crate is a library for managing and monitoring asynchronous tasks within the Tokio runtime. It ensures tasks remain operational by tracking their health and restarting them if they fail or become unresponsive.
Installation
cargo add task-supervisor
Usage
1. Defining a Supervised Task
use async_trait::async_trait;
use std::time::Duration;
use task_supervisor::{SupervisedTask, TaskOutcome};
#[derive(Clone)]
struct MyTask {
pub emoji: char,
}
#[async_trait]
impl SupervisedTask for MyTask {
async fn run(&mut self) -> Result<(), TaskError> {
for _ in 0..15 {
println!("{} Task is running!", self.emoji);
tokio::time::sleep(Duration::from_secs(1)).await;
}
println!("{} Task completed!", self.emoji);
Ok(())
}
}
[!WARNING]
A task must implement Clone
for now, since we need to be able to clone it for restarts.
2. Setting Up and Running the Supervisor
Use the SupervisorBuilder
to create a supervisor and start supervising tasks. The SupervisorHandle
allows dynamic task management:
use std::time::Duration;
use task_supervisor::{SupervisorBuilder, SupervisorHandleError};
#[tokio::main]
async fn main() -> Result<(), SupervisorHandleError> {
let supervisor = SupervisorBuilder::default().build();
let handle = supervisor.run();
let h = handle.clone();
tokio::spawn(async move {
tokio::time::sleep(Duration::from_secs(5)).await;
println!("Adding a task after 5 seconds...");
h.add_task("task", MyTask { emoji: '🆕' })?;
tokio::time::sleep(Duration::from_secs(2)).await;
match h.get_task_status("task").await {
Ok(Some(status)) => println!("Task status: {:?}", status),
Ok(None) => println!("Task not found"),
Err(e) => println!("Error getting task status: {}", e),
}
tokio::time::sleep(Duration::from_secs(5)).await;
println!("Restarting task after 5 seconds...");
h.restart("task")?;
tokio::time::sleep(Duration::from_secs(2)).await;
match h.get_all_task_statuses().await {
Ok(statuses) => {
println!("All task statuses:");
for (name, status) in statuses {
println!(" {}: {:?}", name, status);
}
}
Err(e) => println!("Error getting all task statuses: {}", e),
}
tokio::time::sleep(Duration::from_secs(5)).await;
println!("Killing task after 5 seconds...");
h.kill_task("task")?;
h.shutdown().unwrap();
Ok(())
})?;
handle.wait().await??;
println!("Supervisor stopped! 🫡");
Ok(())
}
The supervisor will:
- Start all initial tasks, executing their run logic.
- Monitor tasks via heartbeats, restarting them if they fail or become unresponsive.
- Allow dynamic task management (add, restart, kill) via the SupervisorHandle.
- Provide task status querying for individual tasks (get_task_status) or all tasks (get_all_task_statuses).
- Exit when all tasks are marked as Dead or Completed.
Contributing
Contributions are welcomed! Please:
- Fork the repository on GitHub.
- Submit a pull request with your changes or open an issue for discussion.
License
This crate is licensed under the MIT License. See the LICENSE file for details.