mod common;
use std::time::Duration;
use common::RunningWorker;
use serde::{Deserialize, Serialize};
use steda::{Error, Result, RetryStrategy, Task, TaskContext};
#[derive(Debug, Deserialize, Serialize)]
struct DeliverDocumentInput {
document_id: String,
destination: String,
}
#[derive(Debug, Deserialize, Serialize)]
struct DeliveryReceipt {
document_id: String,
destination: String,
delivered_on_attempt: u32,
}
const DELIVER_DOCUMENT: Task<DeliverDocumentInput, DeliveryReceipt> = Task::new("deliver-document");
#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<()> {
let steda = common::connect().await?;
let queue = steda.queue("example-retries")?;
queue.create().await?;
let worker = queue
.worker()
.task(DELIVER_DOCUMENT, async |input: DeliverDocumentInput, ctx: TaskContext| {
if ctx.attempt() < 3 {
println!("delivery attempt {}: remote service unavailable", ctx.attempt());
return Err(Error::Other("remote service temporarily unavailable".to_owned()));
}
println!("delivery attempt {}: succeeded", ctx.attempt());
Ok(DeliveryReceipt {
document_id: input.document_id,
destination: input.destination,
delivered_on_attempt: ctx.attempt(),
})
})
.build()?;
let worker = RunningWorker::start(worker);
let task = queue
.spawn(
DELIVER_DOCUMENT,
DeliverDocumentInput {
document_id: "STATEMENT-1001".to_owned(),
destination: "archive@example.invalid".to_owned(),
},
)
.max_attempts(3)
.retry_strategy(RetryStrategy::fixed(Duration::from_millis(250)))
.await?;
let receipt = task.result_with_timeout(Duration::from_secs(10)).await?;
println!("{} delivered to {}", receipt.document_id, receipt.destination);
println!("completed on attempt {}", receipt.delivered_on_attempt);
worker.stop().await?;
Ok(())
}