use ruststream_nats::prelude::*;
use serde::{Deserialize, Serialize};
#[derive(Debug, PartialEq, Deserialize, Serialize, Outgoing)]
struct Order {
id: u64,
}
#[subscriber(CoreSubject::new("orders.created").queue_group("fulfilment"))]
async fn fulfil(order: &Order) -> HandlerOutcome {
tracing::info!(order.id, "order fulfilled");
HandlerOutcome::ack()
}
#[subscriber(CoreWildcard::new("orders.*"))]
async fn audit(order: &Order) -> HandlerOutcome {
tracing::info!(order.id, "order audited");
HandlerOutcome::ack()
}
#[ruststream::app]
fn app() -> impl App {
RustStream::new(AppInfo::new("fulfilment", "0.1.0")).with_broker(
NatsBroker::new("nats://localhost:4222"),
|b| {
b.include(fulfil);
b.include(audit).out_retry(Publish).to("orders.audit");
},
)
}
#[cfg(test)]
mod tests {
use std::error::Error;
use ruststream::testing::TestApp;
use ruststream_nats::prelude::*;
use super::{Order, audit, fulfil};
fn two_replicas() -> impl App {
RustStream::new(AppInfo::new("fulfilment", "0.1.0")).with_broker(
NatsBroker::new("nats://localhost:4222"),
|b| {
b.include(fulfil);
b.include(fulfil);
b.include(audit).out_retry(Publish).to("orders.audit");
},
)
}
#[tokio::test]
async fn each_order_reaches_one_member() -> Result<(), Box<dyn Error>> {
let tb = TestApp::start(two_replicas()).await?;
for id in 1..=4 {
tb.broker::<NatsBroker>()
.message(&Order { id })
.to("orders.created")
.publish()
.await?;
}
let mut fulfilled: Vec<u64> = tb
.broker::<NatsBroker>()
.subscriber("orders.created")
.received::<Order>()
.iter()
.map(|order| order.id)
.collect();
fulfilled.sort_unstable();
assert_eq!(fulfilled, [1, 2, 3, 4]);
tb.broker::<NatsBroker>()
.subscriber("orders.*")
.assert_called(4);
tb.shutdown().await?;
Ok(())
}
}