#![cfg(all(
feature = "memory",
feature = "macros",
feature = "json",
feature = "testing"
))]
mod common;
use std::time::Duration;
use ruststream::OutgoingMessage;
use ruststream::memory::prelude::*;
use ruststream::runtime::{ContextKind, Outgoing, PublishTransform, Reads};
use ruststream::testing::expect_published;
use common::{Order, Receipt, Wire, connected};
struct Envelope;
impl<K: ContextKind, Options> PublishTransform<K, Options> for Envelope {
type Destination = Reads;
fn apply(&self, out: &mut Outgoing<'_>, _options: &mut Option<Options>, _cx: &K::View<'_>) {
out.headers_mut().insert("x-envelope", b"1".to_vec());
}
}
#[tokio::test]
async fn a_bare_policy_pairs_into_a_live_publisher() {
let connected = MemoryBroker::retaining(Retention::Messages(nonzero!(8)))
.connect()
.await
.expect("memory connect is infallible");
let publisher = Publish
.pair(&connected)
.await
.expect("memory pairing is infallible");
publisher
.message(&Wire::of(b"paired"))
.to("policy.out")
.publish()
.await
.expect("publish through the paired publisher");
let seen = expect_published(&connected, "policy.out", 1, Duration::from_secs(2)).await;
assert_eq!(seen.len(), 1);
assert_eq!(seen[0].payload(), b"paired");
}
#[tokio::test]
async fn a_request_policy_pairs_into_a_requester() {
let connected = MemoryBroker::new()
.connect()
.await
.expect("memory connect is infallible");
let requester = Request
.pair(&connected)
.await
.expect("memory pairing is infallible");
let unanswered = RequestReply::request(
&requester,
OutgoingMessage::new("policy.void", b"ping".as_slice()),
Duration::from_millis(50),
)
.await;
assert!(unanswered.is_err(), "{unanswered:?}");
}
#[subscriber("policy.requests", reply("policy.replies"))]
async fn respond(order: &Order) -> Receipt {
Receipt { id: order.id }
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn a_reply_wiring_keeps_its_transform_through_the_pairing() {
let broker = MemoryBroker::retaining(Retention::Messages(nonzero!(8)));
let publisher = broker.publisher();
let live = connected(&broker).await;
let app = RustStream::new(AppInfo::new("policy", "0.1.0")).with_broker(broker, |b| {
b.include(respond).out(Reply, Publish).transform(Envelope);
});
let running = app.start().await.expect("startup failed");
publisher
.message(&Order { id: 7 })
.to("policy.requests")
.publish()
.await
.expect("publish request");
let seen = expect_published(&live, "policy.replies", 1, Duration::from_secs(2)).await;
assert_eq!(seen.len(), 1, "the reply must be published");
assert_eq!(
seen[0].headers().get("x-envelope"),
Some(b"1".as_slice()),
"the transform stack must survive pairing",
);
running.shutdown().await.expect("graceful shutdown failed");
}