use ash_flare::{RestartPolicy, RestartStrategy, SupervisorHandle, SupervisorSpec, Worker};
use async_trait::async_trait;
use std::time::Duration;
use tokio::time::sleep;
#[derive(Debug)]
struct CounterError(String);
impl std::fmt::Display for CounterError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
impl std::error::Error for CounterError {}
struct Counter {
name: String,
max_count: Option<u32>,
}
impl Counter {
fn new(name: impl Into<String>, max_count: Option<u32>) -> Self {
Self {
name: name.into(),
max_count,
}
}
}
#[async_trait]
impl Worker for Counter {
type Error = CounterError;
async fn run(&mut self) -> Result<(), Self::Error> {
let mut count = 0;
loop {
count += 1;
println!("[{}] count: {}", self.name, count);
if let Some(max) = self.max_count {
if count >= max {
return Err(CounterError(format!("{} reached max", self.name)));
}
}
sleep(Duration::from_millis(800)).await;
}
}
async fn shutdown(&mut self) -> Result<(), Self::Error> {
println!("[{}] shutdown", self.name);
Ok(())
}
}
#[tokio::main]
async fn main() {
println!("=== Counter Example: OneForOne Strategy ===\n");
let spec = SupervisorSpec::new("counter_supervisor")
.with_restart_strategy(RestartStrategy::OneForOne)
.with_worker(
"stable",
|| Counter::new("stable", None),
RestartPolicy::Permanent,
)
.with_worker(
"crashes",
|| Counter::new("crashes", Some(5)),
RestartPolicy::Permanent, )
.with_worker(
"temporary",
|| Counter::new("temporary", Some(8)),
RestartPolicy::Temporary, );
let supervisor = SupervisorHandle::start(spec);
sleep(Duration::from_secs(15)).await;
println!("\nShutting down...");
supervisor.shutdown().await.ok();
sleep(Duration::from_millis(200)).await;
}