#[cfg(not(feature = "controller"))]
compile_error!(
"This example requires the `controller` feature: cargo run --example slots --features controller"
);
use std::sync::Arc;
use std::time::Duration;
use taskvisor::prelude::*;
use tokio::sync::Notify;
fn job(name: &'static str, duration: Duration) -> TaskSpec {
job_with_start(name, duration, None)
}
fn job_with_start(
name: &'static str,
duration: Duration,
started: Option<Arc<Notify>>,
) -> TaskSpec {
let task: TaskRef = TaskFn::arc(name, move |ctx| {
let started = started.clone();
async move {
if let Some(started) = &started {
started.notify_one();
}
println!(" [{name}] started");
let start = tokio::time::Instant::now();
match ctx.run_until_cancelled(tokio::time::sleep(duration)).await {
Ok(()) => {
println!(" [{name}] completed in {:?}", start.elapsed());
Ok(())
}
Err(canceled) => {
println!(" [{name}] cancelled after {:?}", start.elapsed());
Err(canceled)
}
}
}
});
TaskSpec::once(task)
}
#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let sup = Supervisor::builder(SupervisorConfig::default())
.with_controller(taskvisor::ControllerConfig::default())
.build();
let handle = sup.serve();
println!("=== Queue Policy ===");
println!("Submit 3 jobs with the same name — they run one-by-one.\n");
let mut queued = Vec::new();
for i in 1..=3 {
let spec = job("queued-job", Duration::from_millis(400));
let (_id, waiter) = handle
.submit_and_watch(taskvisor::ControllerSpec::queue(spec))
.await?;
queued.push(waiter);
println!(" submitted #{i}");
}
for (index, waiter) in queued.into_iter().enumerate() {
println!(" queued #{} -> {:?}", index + 1, waiter.wait().await?);
}
println!("\n=== Replace Policy ===");
println!("Submit a long job, then replace it with a short one.\n");
let long_started = Arc::new(Notify::new());
let long = job_with_start(
"replace-job",
Duration::from_secs(5),
Some(Arc::clone(&long_started)),
);
let (_long_id, long_waiter) = handle
.submit_and_watch(taskvisor::ControllerSpec::replace(long))
.await?;
long_started.notified().await;
let short = job("replace-job", Duration::from_millis(200));
let (_short_id, short_waiter) = handle
.submit_and_watch(taskvisor::ControllerSpec::replace(short))
.await?;
println!(" long -> {:?}", long_waiter.wait().await?);
println!(" short -> {:?}", short_waiter.wait().await?);
println!("\n=== DropIfRunning Policy ===");
println!("Submit a job, then try to submit another while the first is running.\n");
let first_started = Arc::new(Notify::new());
let first = job_with_start(
"drop-job",
Duration::from_millis(600),
Some(Arc::clone(&first_started)),
);
let (_first_id, first_waiter) = handle
.submit_and_watch(taskvisor::ControllerSpec::drop_if_running(first))
.await?;
first_started.notified().await;
let second = job("drop-job", Duration::from_millis(100));
let (_second_id, second_waiter) = handle
.submit_and_watch(taskvisor::ControllerSpec::drop_if_running(second))
.await?;
println!(" second -> {:?}", second_waiter.wait().await?);
println!(" first -> {:?}", first_waiter.wait().await?);
println!("\nDone.");
handle.shutdown().await?;
Ok(())
}