Design
Where ruststream-fred sits: between the RustStream runtime and the fred client, a client of its
own per subscription, one shared pool.
The diagram as text
- Your service: #[subscriber] handlers; RustStream::new(..) .with_broker(..)
- RustStream core: Runtime: dispatch, decode, settlement
- ruststream-fred: Subscribers of streams, lists and channels; Publishers of the same three forms; RedisStream RedisList RedisPubSub; Pipeline window of .pipeline(); RedisBroker topology, pool, credentials
- fred: A client of its own per subscription; Pool 4 connections
- #[subscriber] handlers → Runtime: dispatch, decode, settlement: mounted
- Runtime: dispatch, decode, settlement → Subscribers of streams, lists and channels: polls
- Runtime: dispatch, decode, settlement → Publishers of the same three forms: publishes
- Subscribers of streams, lists and channels → A client of its own per subscription
- Publishers of the same three forms → Pool 4 connections
- A client of its own per subscription → Redis or Valkey: standalone, cluster or sentinel
- Pool 4 connections → Redis or Valkey: standalone, cluster or sentinel
The crate implements the core's broker traits over fred. The runtime above it is the same for every broker. Everything Redis-specific is in this crate: the descriptors of the three transports, what an acknowledgement means on each, where a retry copy goes, and the pipeline window.
A descriptor resolves once, at startup, against the connected broker, and yields a subscriber. The subscriber is a stream of deliveries that the runtime polls. The runtime decodes each delivery, runs the handler and settles the delivery with its outcome. A publish policy pairs with the connected broker into a publisher.
Each subscription reads on a client of its own, so a blocked read never holds up a publish. Publishes, settlements and the commands a handler sends share the pool. Lifecycle draws when each client opens and closes, and Path the way of one entry.
A stream entry carries the payload in a field named _payload and each header in a field
h:<name>, so XADD and XREADGROUP keep both. A list entry and a channel message carry the
headers in a frame around the payload: a binary frame, or a codec envelope when the descriptor
names a codec.