use std::error::Error;
use std::time::Duration;
use ruststream::memory::prelude::*;
use serde::{Deserialize, Serialize};
use tokio::time::sleep;
#[derive(Debug, Outgoing, Serialize, Deserialize)]
struct Job {
id: u64,
}
#[subscriber("audit", start_at(MemoryPosition::start()))]
async fn record(entry: &Job) -> HandlerOutcome {
println!("audit: entry {}", entry.id);
HandlerOutcome::ack()
}
#[subscriber("jobs")]
async fn work(job: &Job, Ctx(seeker): Ctx<SeekHandle>) -> HandlerOutcome {
if job.id == 999 {
if seeker.seek(MemoryPosition::sequence(3)).await.is_err() {
return HandlerOutcome::retry();
}
return HandlerOutcome::ack();
}
println!("jobs: processed {}", job.id);
HandlerOutcome::ack()
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let broker = MemoryBroker::retaining(Retention::Messages(nonzero!(64)));
let ingress = broker.publisher();
for id in 1..=2u64 {
ingress.message(&Job { id }).to("audit").publish().await?;
}
let app = RustStream::new(AppInfo::new("seek-demo", "0.1.0")).with_broker(broker, |b| {
b.include(work);
b.include(record);
});
let running = app.start().await?;
for id in [1, 999, 3, 4] {
ingress.message(&Job { id }).to("jobs").publish().await?;
}
sleep(Duration::from_millis(100)).await;
running.shutdown().await?;
println!("ok: replayed the audit history and skipped the poisoned region");
Ok(())
}