mod common;
use std::{future, sync::Arc, time::Duration};
use common::RunningWorker;
use steda::{CancellationPolicy, Error, Result, Task, TaskContext};
use tokio::sync::Notify;
const MANUAL_CANCELLATION: Task<(), ()> = Task::new("manual-cancellation");
const DEADLINE_CANCELLATION: Task<(), ()> = Task::new("deadline-cancellation");
#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<()> {
let steda = common::connect().await?;
let queue = steda.queue("example-cancellation")?;
queue.create().await?;
let manual_started = Arc::new(Notify::new());
let worker = queue
.worker()
.task(MANUAL_CANCELLATION, {
let manual_started = Arc::clone(&manual_started);
move |(), _ctx: TaskContext| {
let manual_started = Arc::clone(&manual_started);
async move {
println!("manual cancellation: handler started");
manual_started.notify_one();
future::pending::<Result<()>>().await
}
}
})
.task(DEADLINE_CANCELLATION, async |(), _ctx: TaskContext| {
println!("deadline cancellation: handler started");
future::pending::<Result<()>>().await
})
.build()?;
let worker = RunningWorker::start(worker);
let manual = queue.spawn(MANUAL_CANCELLATION, ()).await?;
tokio::time::timeout(Duration::from_secs(5), manual_started.notified())
.await
.map_err(|_| Error::Timeout("timed out waiting for manual task to start".to_owned()))?;
manual.cancel().await?;
match manual.result_with_timeout(Duration::from_secs(5)).await {
Err(Error::Cancelled) => println!("manual cancellation: task cancelled"),
Err(error) => return Err(error),
Ok(()) => return Err(Error::Other("cancelled task unexpectedly completed".to_owned())),
}
let deadline = queue
.spawn(DEADLINE_CANCELLATION, ())
.cancellation(CancellationPolicy::new().max_duration(Duration::from_secs(1)))
.await?;
match deadline.result_with_timeout(Duration::from_secs(5)).await {
Err(Error::Cancelled) => println!("deadline cancellation: task cancelled automatically"),
Err(error) => return Err(error),
Ok(()) => {
return Err(Error::Other("deadline-limited task unexpectedly completed".to_owned()));
}
}
worker.stop().await?;
Ok(())
}