Idempotency
How keys, caching, and joining work in practice.
A working queue in three steps.
Start a queue
Workers spawn immediately. There is no separate run() call to forget.
use agentq::{LaneConfig, Priority, Queue};
let queue = Queue::builder() .lane(Priority::High, LaneConfig { capacity: 32, permits: 1 }) .lane(Priority::Low, LaneConfig { capacity: 128, permits: 4 }) .start();Lanes you do not configure use LaneConfig::default().
Build a job
A job is an idempotency key, a priority, and an async closure that returns
a String on success.
use agentq::Job;
let job = Job::new( "charge-order-4821".to_string(), Priority::High, Box::new(|| Box::pin(async { Ok("charged".to_string()) })),);The key is yours to choose. It is what makes a retry recognisable as the same work.
Push it and take the result
let output = queue.push_and_wait(job).await?;That one call covers three cases: the key already completed and you get the cached output, the key is running and you join it, or the work is queued and you wait for it.
use agentq::{Job, LaneConfig, Priority, Queue};
#[tokio::main]async fn main() -> Result<(), Box<dyn std::error::Error>> { let queue = Queue::builder() .lane(Priority::High, LaneConfig { capacity: 32, permits: 1 }) .start();
let job = Job::new( "charge-order-4821".to_string(), Priority::High, Box::new(|| Box::pin(async { Ok("charged".to_string()) })), );
let output = queue.push_and_wait(job).await?; println!("{output}");
Ok(())}