Path
The stages one delivery passes, from the broker's stream to its settlement, in the order the runtime runs them.
The diagram as text
- Subscription stream opened once, at startup → Dispatch loop the delivery in a reused slot
- Dispatch loop the delivery in a reused slot → Consume layers the first one added is outermost
- Consume layers the first one added is outermost → Decode the mounting's codec, or the bytes
- Decode the mounting's codec, or the bytes → Handler async fn under #[subscriber]
- Handler async fn under #[subscriber] → Reply encoded into the loop's buffer
- Reply encoded into the loop's buffer → Publish transforms in the order the chain names them
- Publish transforms in the order the chain names them → Publish layers around every publish
- Publish layers around every publish → Publisher sends the reply to the broker
- Publisher sends the reply to the broker → Settlement ack, or retry if the reply failed
The subscription and the reply's publisher are resolved once, when the app starts, against the connected broker. Nothing on this path looks a subscription or a publisher up per message.
Consume layers wrap the decode, so a layer sees a delivery even when its payload does not decode. A payload that does not decode never reaches the handler: the failure policy settles it.
A handler with no reply settles right after its body. A handler that returns an error outcome skips the reply. A reply that fails to publish settles the delivery with a retry, so the request is not lost.
The reply goes where its type declares. A publisher that only reads the bytes is lent the dispatch loop's own buffer, so a reply allocates nothing. A publisher that keeps the bytes gets a buffer of its own.