#![cfg_attr(not(test), allow(dead_code, unused_imports))]
use std::time::Duration;
use serde::{Deserialize, Serialize};
#[derive(Debug, PartialEq, Deserialize, Serialize, ruststream::Outgoing)]
struct Order {
id: u64,
}
async fn charge(order: &Order) {
tokio::time::sleep(Duration::from_secs(1)).await;
tracing::info!(order.id, "charged");
}
mod pool {
use std::error::Error;
use futures::future::join_all;
use ruststream::memory::prelude::*;
use ruststream::testing::TestApp;
use tokio::time::Instant;
use super::{Order, charge};
#[subscriber("orders", workers(4))]
async fn bill(order: &Order) -> HandlerOutcome {
charge(order).await;
HandlerOutcome::ack()
}
fn app() -> impl App {
RustStream::new(AppInfo::new("billing", "0.1.0")).with_broker(MemoryBroker::new(), |b| {
b.include(bill);
})
}
#[tokio::test]
async fn four_orders_are_charged_together() -> Result<(), Box<dyn Error>> {
tokio::time::pause();
let tb = TestApp::start(app()).await?;
let broker = tb.broker::<MemoryBroker>();
let orders: Vec<Order> = (1..=4).map(|id| Order { id }).collect();
let started = Instant::now();
for published in join_all(
orders
.iter()
.map(|order| broker.message(order).to("orders").publish()),
)
.await
{
published?;
}
assert_eq!(started.elapsed().as_secs(), 1);
broker
.subscriber("orders")
.assert_called(4)
.settled(HandlerOutcome::ack());
Ok(())
}
}
mod by_key {
use std::error::Error;
use futures::future::join_all;
use ruststream::HeaderMap;
use ruststream::memory::PARTITION_KEY_HEADER;
use ruststream::memory::prelude::*;
use ruststream::testing::TestApp;
use tokio::time::Instant;
use super::{Order, charge};
#[subscriber("orders", workers(4, by_key))]
async fn bill(order: &Order) -> HandlerOutcome {
charge(order).await;
HandlerOutcome::ack()
}
fn app() -> impl App {
RustStream::new(AppInfo::new("billing", "0.1.0")).with_broker(MemoryBroker::new(), |b| {
b.include(bill);
})
}
#[tokio::test]
async fn one_customer_waits_for_its_own_orders_only() -> Result<(), Box<dyn Error>> {
tokio::time::pause();
let tb = TestApp::start(app()).await?;
let broker = tb.broker::<MemoryBroker>();
let orders: Vec<(Order, HeaderMap)> = [(1, "alice"), (2, "bob"), (3, "alice"), (4, "bob")]
.into_iter()
.map(|(id, customer)| {
let mut headers = HeaderMap::new();
headers.insert(PARTITION_KEY_HEADER, customer);
(Order { id }, headers)
})
.collect();
let started = Instant::now();
for published in join_all(orders.iter().map(|(order, headers)| {
broker
.message(order)
.with_headers(headers.clone())
.to("orders")
.publish()
}))
.await
{
published?;
}
assert_eq!(started.elapsed().as_secs(), 2);
broker
.subscriber("orders")
.assert_called(4)
.settled(HandlerOutcome::ack());
Ok(())
}
}
fn main() {}