use std::convert::Infallible;
use std::sync::Arc;
use std::sync::atomic::{AtomicU64, Ordering};
use ruststream::memory::prelude::*;
use ruststream::testing::TestApp;
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize, schemars::JsonSchema)]
struct Order {
id: u64,
}
#[derive(Clone)]
struct CreateOrder {
processed: Arc<AtomicU64>,
}
impl CreateOrder {
fn execute(&self, order: &Order) {
self.processed.fetch_add(order.id, Ordering::Relaxed);
}
}
struct AppState {
create_order: CreateOrder,
}
impl FromRef<AppState> for CreateOrder {
fn from_ref(state: &AppState) -> Self {
state.create_order.clone()
}
}
struct Receive;
impl Handle<Order, (), (), (), AppState> for Receive {
async fn handle(
&self,
order: &Order,
_outs: &(),
ctx: &mut Context<'_, (), AppState>,
) -> Result<(), HandlerOutcome> {
let State(create_order) =
match <State<CreateOrder> as FromContext<(), AppState>>::from_context(ctx).await {
Ok(value) => value,
Err(rejection) => return Err(HandlerOutcome::from(rejection)),
};
create_order.execute(order);
Ok(())
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let processed = Arc::new(AtomicU64::new(0));
let create_order = CreateOrder {
processed: processed.clone(),
};
let app = RustStream::new(AppInfo::new("orders", "0.1.0"))
.on_startup(async move |()| Ok::<_, Infallible>(AppState { create_order }))
.with_broker(MemoryBroker::new(), |b| {
b.include(subscriber("orders", Receive).build());
});
let tb = TestApp::start(app).await?;
tb.publish("orders", &Order { id: 40 }).await?;
tb.publish("orders", &Order { id: 2 }).await?;
println!("processed total = {}", processed.load(Ordering::Relaxed));
Ok(())
}