Design
Where ruststream-lapin sits: between the RustStream runtime and the lapin client, one
connection, a channel per subscription.
The diagram as text
- Your service: #[subscriber] handlers; RustStream::new(..) .with_broker(..)
- RustStream core: Runtime: dispatch, lanes, settlement
- ruststream-lapin: LapinSubscriber yields LapinMessage; LapinPublisher, ConfirmsPublisher, ServerTxPublisher; LapinBroker configuration; RabbitQueue, RabbitQuorumQueue, RabbitExchange; LapinRequester
- lapin: Connection one per broker; A channel per subscription; Shared publish channel; confirms, transactions and requests: their own
- #[subscriber] handlers → Runtime: dispatch, lanes, settlement: mounted
- Runtime: dispatch, lanes, settlement → LapinSubscriber yields LapinMessage: polls the stream
- LapinSubscriber yields LapinMessage → A channel per subscription
- LapinPublisher, ConfirmsPublisher, ServerTxPublisher → Shared publish channel; confirms, transactions and requests: their own
- LapinRequester → Shared publish channel; confirms, transactions and requests: their own
- A channel per subscription → RabbitMQ node
- Shared publish channel; confirms, transactions and requests: their own → RabbitMQ node
The crate implements the core's broker traits over lapin, a pure-Rust AMQP 0.9.1 client. The runtime above it is the same for every broker. Everything RabbitMQ-specific is in this crate: the queue descriptors, the frames a settlement sends, where a retry goes, and the three publishing modes.
One broker opens one connection. Each subscription consumes on a channel of its own, so its prefetch window and its errors stay its own. Fire-and-forget publishers share one channel. A confirms publisher, a transaction publisher and a requester each open a channel of their own on first use, because a confirm mode, a transaction and a reply consumer are channel state.
A channel error closes one channel and leaves the connection up. A publisher's channel opens again on its next use, so one publish to a missing exchange does not stop the service publishing.
LapinBroker declares nothing by default. A descriptor then
states the topology the service expects, and a missing queue fails its subscription.
declare_topology(true) makes each
subscription declare its exchanges, its queue and its bindings, in that order.
A requester reads its replies in a task on the runtime the broker connected on, whichever thread makes the first request.
How the pieces start and stop is on Lifecycle, and the way of one delivery on Path.