Skip to main content

Ctx

Ctx<K> passes one field of the broker's per-delivery context to the handler as a parameter.

K is the broker's key for the field, the same key ctx.context(key) reads, so the body needs no &mut Context. Ctx takes any CtxKey: a broker's context key, or MainRuntime. The #[subscriber] attribute infers the context type from the key. A key only reads a context that the broker provides: Ctx<Position> compiles on a retaining memory broker, not on a plain one. Ctx<MainRuntime> is the one key that reads no broker field: it binds the application's runtime for a handler on dedicated threads. Ctx<K> is an extractor, resolved before the body runs.

Example​

/// Where an order sits in the broker's log, published on `located`.
#[derive(Debug, PartialEq, Deserialize, Serialize, Outgoing)]
#[outgoing(name = "located")]
struct Located {
order: u64,
sequence: usize,
}

/// `Ctx<Position>` hands the body this delivery's position: one field of the broker's
/// per-delivery context, with no `&mut Context` parameter.
#[subscriber("orders", reply)]
async fn locate(order: &Order, Ctx(at): Ctx<Position>) -> Result<Located, HandlerOutcome> {
let MemoryPosition::Sequence(sequence) = at else {
return Err(HandlerOutcome::drop());
};
Ok(Located {
order: order.id,
sequence,
})
}

fn app() -> impl App {
// A retaining broker numbers its messages; its deliveries carry the position.
let broker = MemoryBroker::retaining(Retention::Messages(nonzero!(16)));
RustStream::new(AppInfo::new("orders", "0.1.0")).with_broker(broker, |b| {
b.include(locate);
})
}