Expand description
Optional typed per-delivery context exposing native JetStream metadata.
A handler reads native JetStream delivery metadata - the stream and consumer names, the stream
and consumer sequence numbers, the server-side redelivery count, and the pending count - by
declaring JetStreamContext as its per-delivery context and reading fields with the
compile-time keys. The runtime builds the context once per delivery via
BuildContext; resolving a key is a direct field read, with no
hashing, boxing, or downcasting.
This is purely additive: the default context is () (no fields), so existing handlers are
unaffected. Opting in means changing the handler’s context type to JetStreamContext.
These fields are genuinely native: they come from the JetStream $JS.ACK reply subject, not
from the payload or the message Headers, so they are not reachable any
other way. Core (non-JetStream) NATS deliveries carry no such metadata - their only native datum
is the reply inbox, already surfaced as the reply-to header - so Core handlers should keep the
default () context. A handler bound to JetStreamContext still works on a Core subscription;
every key just reads None there.
§Examples
use ruststream::IncomingMessage;
use ruststream::runtime::{Context, HandlerResult};
use ruststream_nats::context::{JetStreamContext, keys};
async fn handle<M: IncomingMessage>(
_msg: &M,
ctx: &mut Context<'_, JetStreamContext>,
) -> HandlerResult {
// `None` on a core delivery; the stream sequence on a JetStream one.
if let Some(seq) = ctx.context(keys::STREAM_SEQUENCE) {
println!("stream sequence {seq}");
}
// The server-side delivery count distinguishes a first delivery from a redelivery.
if ctx.context(keys::DELIVERED).is_some_and(|n| n > 1) {
println!("redelivery");
}
HandlerResult::Ack
}Modules§
Structs§
- JetStream
Context - Native
JetStreamper-delivery metadata, built once per delivery from the broker message.