use std::sync::Arc;
use mailrs_outbound_queue::{
InMemoryQueueStore, QueueStatus, QueueStore, retry_delay_secs, should_bounce,
};
#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let store: Arc<dyn QueueStore> = Arc::new(InMemoryQueueStore::new());
let now = chrono::Utc::now().timestamp();
let id1 = store
.enqueue(
"alice@x.org",
"bob@y.com",
"y.com",
b"hi bob",
None,
now,
false,
)
.await?;
let id2 = store
.enqueue(
"alice@x.org",
"carol@y.com",
"y.com",
b"hi carol",
None,
now,
false,
)
.await?;
println!("enqueued #{id1}, #{id2}");
let pending = store.dequeue(now, 50).await?;
println!("dequeued {} message(s) ready for delivery", pending.len());
store.mark_inflight(id1, now).await?;
store.mark_delivered(id1, now + 1).await?;
let attempts_after = 1;
let delay = retry_delay_secs(attempts_after);
store
.mark_failed(
id2,
"transient error: server too busy",
now + delay as i64,
now,
)
.await?;
println!("retry delay after {attempts_after} attempt(s): {delay}s");
store
.add_suppression("blocked@y.com", "hard bounce", Some(550))
.await?;
assert!(store.is_suppressed("blocked@y.com").await);
assert!(!store.is_suppressed("alice@x.org").await);
assert!(!should_bounce(1, 8));
assert!(should_bounce(9, 8));
println!("\nqueue stats:");
for (status, count) in store.queue_stats().await? {
println!(" {status:>10} {count}");
}
let m1 = store.get_message(id1).await?.unwrap();
let m2 = store.get_message(id2).await?.unwrap();
assert_eq!(m1.status, QueueStatus::Delivered);
assert_eq!(m2.status, QueueStatus::Pending);
assert_eq!(m2.attempts, 1);
println!("\nall trait-surface ops worked against the in-memory store.");
Ok(())
}