#![cfg(feature = "testing")]
use fred::clients::Pool;
use fred::interfaces::ListInterface;
use ruststream::testing::TestApp;
use ruststream_fred::context::keys;
use ruststream_fred::prelude::*;
use serde::{Deserialize, Serialize};
const URL: &str = "redis://localhost:6379";
#[derive(Debug, Deserialize, Outgoing, PartialEq, Serialize)]
struct Order {
id: u64,
}
async fn audit(pool: &Pool, order: &Order) -> HandlerOutcome {
let body = format!(r#"{{"id":{}}}"#, order.id);
match pool.lpush::<i64, _, _>("audit", body).await {
Ok(_) => HandlerOutcome::ack(),
Err(_) => HandlerOutcome::retry(),
}
}
#[subscriber(RedisStream::new("orders").group("workers"))]
async fn from_stream(order: &Order, Ctx(pool): Ctx<keys::FredPool>) -> HandlerOutcome {
audit(&pool, order).await
}
#[subscriber(RedisList::new("jobs").reliable())]
async fn from_reliable_list(order: &Order, Ctx(pool): Ctx<keys::FredPool>) -> HandlerOutcome {
audit(&pool, order).await
}
#[subscriber(RedisList::new("tasks"))]
async fn from_plain_list(order: &Order, Ctx(pool): Ctx<keys::FredPool>) -> HandlerOutcome {
audit(&pool, order).await
}
#[subscriber(RedisPubSub::new("events"))]
async fn from_channel(order: &Order, Ctx(pool): Ctx<keys::FredPool>) -> HandlerOutcome {
audit(&pool, order).await
}
macro_rules! writes_through_the_pool {
($test:ident, $handler:ident, $name:literal) => {
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn $test() {
let app = RustStream::new(AppInfo::new("pool", "0.1.0")).with_broker(
RedisBroker::standalone(URL),
|b| {
b.include($handler);
},
);
let tb = TestApp::start(app).await.expect("start");
tb.broker::<RedisBroker>()
.message(&Order { id: 5 })
.to($name)
.publish()
.await
.expect("publish");
tb.broker::<RedisBroker>()
.subscriber($name)
.assert_called_once()
.settled(HandlerOutcome::ack());
tb.broker::<RedisBroker>()
.published::<Order>("audit")
.assert_called_once()
.with(&Order { id: 5 });
tb.shutdown().await.expect("shutdown");
}
};
}
writes_through_the_pool!(
a_stream_handler_writes_through_the_pool,
from_stream,
"orders"
);
writes_through_the_pool!(
a_reliable_list_handler_writes_through_the_pool,
from_reliable_list,
"jobs"
);
writes_through_the_pool!(
a_plain_list_handler_writes_through_the_pool,
from_plain_list,
"tasks"
);
writes_through_the_pool!(
a_channel_handler_writes_through_the_pool,
from_channel,
"events"
);
#[subscriber(RedisStream::new("orders").group("workers"))]
async fn with_entry_id(
order: &Order,
Ctx(entry): Ctx<keys::EntryId>,
Ctx(pool): Ctx<keys::FredPool>,
) -> HandlerOutcome {
let _ = (order, entry, pool);
HandlerOutcome::ack()
}
#[subscriber(RedisPubSub::new("events"))]
async fn with_channel(
order: &Order,
Ctx(channel): Ctx<keys::Channel>,
Ctx(pool): Ctx<keys::FredPool>,
) -> HandlerOutcome {
let _ = (order, channel, pool);
HandlerOutcome::ack()
}
#[test]
fn the_pool_rides_beside_a_forms_own_keys() {
let app = RustStream::new(AppInfo::new("pool", "0.1.0")).with_broker(
RedisBroker::standalone("redis://localhost:6379"),
|b| {
b.include(with_entry_id);
b.include(with_channel);
},
);
let _ = app;
}