#![cfg(feature = "testing")]
use std::time::Duration;
use ruststream::testing::TestApp;
use ruststream_fred::{RedisBroker, RedisList, RedisPubSub, RedisStream};
use serde::{Deserialize, Serialize};
use ruststream::prelude::*;
const URL: &str = "redis://localhost:6379";
const MIN_IDLE: Duration = Duration::from_secs(30);
#[derive(Debug, Deserialize, Outgoing, PartialEq, Serialize)]
struct Order {
id: u64,
}
#[subscriber(RedisStream::new("orders").group("workers"))]
async fn never_ready(order: &Order) -> HandlerOutcome {
let _ = order;
HandlerOutcome::retry()
}
#[subscriber(RedisStream::claiming("claimed", MIN_IDLE).group("workers"))]
async fn never_ready_claimed(order: &Order) -> HandlerOutcome {
let _ = order;
HandlerOutcome::retry()
}
#[subscriber(RedisList::new("jobs").reliable())]
async fn never_ready_job(order: &Order) -> HandlerOutcome {
let _ = order;
HandlerOutcome::retry()
}
#[subscriber(RedisPubSub::new("events"))]
async fn never_ready_event(order: &Order) -> HandlerOutcome {
let _ = order;
HandlerOutcome::retry()
}
fn app() -> impl App<State = ()> {
RustStream::new(AppInfo::new("orders", "0.1.0")).with_broker(
RedisBroker::standalone(URL),
|b| {
b.include(never_ready)
.max_attempts(nonzero!(3u32))
.dead_letter("orders.dead");
b.include(never_ready_claimed)
.max_attempts(nonzero!(3u32))
.dead_letter("claimed.dead");
b.include(never_ready_job)
.max_attempts(nonzero!(2u32))
.dead_letter("jobs.failed");
b.include(never_ready_event)
.max_attempts(nonzero!(2u32))
.dead_letter("events.dead");
},
)
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn a_stream_stops_at_the_cap_and_hands_the_last_delivery_over() {
let tb = TestApp::start(app()).await.expect("startup failed");
tb.broker::<RedisBroker>()
.message(&Order { id: 1 })
.to("orders")
.publish()
.await
.expect("publish");
tb.broker::<RedisBroker>()
.subscriber("orders")
.assert_called(3);
tb.broker::<RedisBroker>()
.published::<Order>("orders.dead")
.assert_called_once()
.with(&Order { id: 1 });
tb.shutdown().await.expect("shutdown");
}
#[tokio::test(start_paused = true)]
async fn a_claiming_subscription_caps_on_the_servers_own_count() {
let tb = TestApp::start(app()).await.expect("startup failed");
tb.broker::<RedisBroker>()
.message(&Order { id: 2 })
.to("claimed")
.publish()
.await
.expect("publish");
tb.broker::<RedisBroker>()
.subscriber("claimed")
.assert_called_once();
tb.advance(MIN_IDLE).await.expect("first claim back");
tb.advance(MIN_IDLE).await.expect("second claim back");
tb.broker::<RedisBroker>()
.subscriber("claimed")
.assert_called(3);
tb.broker::<RedisBroker>()
.published::<Order>("claimed.dead")
.assert_called_once()
.with(&Order { id: 2 });
tb.shutdown().await.expect("shutdown");
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn a_reliable_list_stops_at_the_cap() {
let tb = TestApp::start(app()).await.expect("startup failed");
tb.broker::<RedisBroker>()
.message(&Order { id: 3 })
.to("jobs")
.publish()
.await
.expect("publish");
tb.broker::<RedisBroker>()
.subscriber("jobs")
.assert_called(2);
tb.broker::<RedisBroker>()
.published::<Order>("jobs.failed")
.assert_called_once()
.with(&Order { id: 3 });
tb.shutdown().await.expect("shutdown");
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn a_channel_stops_at_the_cap() {
let tb = TestApp::start(app()).await.expect("startup failed");
tb.broker::<RedisBroker>()
.message(&Order { id: 4 })
.to("events")
.publish()
.await
.expect("publish");
tb.broker::<RedisBroker>()
.subscriber("events")
.assert_called(2);
tb.broker::<RedisBroker>()
.published::<Order>("events.dead")
.assert_called_once()
.with(&Order { id: 4 });
tb.shutdown().await.expect("shutdown");
}