#[cfg(not(feature = "controller"))]
compile_error!(
"This example requires the `controller` feature: cargo run --example admission --features controller"
);
use std::time::Duration;
use taskvisor::ControllerSpec;
use taskvisor::prelude::*;
fn job(name: &'static str, dur: Duration) -> TaskSpec {
let task: TaskRef = TaskFn::arc(name, move |ctx: CancellationToken| async move {
tokio::select! {
_ = tokio::time::sleep(dur) => Ok(()),
_ = ctx.cancelled() => Err(TaskError::Canceled),
}
});
TaskSpec::once(task).with_slot("deploy")
}
#[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!("Slot 'deploy' admits at most one task at a time.\n");
println!("1) submit deploy-v1 (Queue) to the idle slot");
let (_id, v1) = handle
.submit_and_watch(ControllerSpec::queue(job(
"deploy-v1",
Duration::from_millis(200),
)))
.await?;
tokio::time::sleep(Duration::from_millis(50)).await;
println!(" deploy-v1 admitted, now running\n");
println!("2) submit deploy-v2 (DropIfRunning) while the slot is busy");
let (_id, v2) = handle
.submit_and_watch(ControllerSpec::drop_if_running(job(
"deploy-v2",
Duration::from_millis(200),
)))
.await?;
match v2.wait().await? {
TaskOutcome::Rejected { reason } => {
println!(" deploy-v2 -> Rejected ({reason}) — never ran\n");
}
other => println!(" deploy-v2 -> {other:?} (unexpected)\n"),
}
println!("3) await the admitted task");
println!(" deploy-v1 -> {:?}", v1.wait().await?);
handle.shutdown().await?;
println!("\nDone.");
Ok(())
}