Settlement
How a delivery is settled: what the handler returns, what a failure policy decides, and where a retry ends.
The diagram as text
- A delivery → Decode the payload
- Decode the payload → Handler runs: decoded
- Decode the payload → Does not decode: drop by default
- Handler runs → Outcome what the body returned: returns
- Handler runs → Panics: fail_fast by default, the service stops
- Does not decode: drop by default → Outcome what the body returned
- Panics: fail_fast by default, the service stops → Outcome what the body returned: other policies
- Outcome what the body returned → ack() acknowledged
- Outcome what the body returned → drop() rejected
- Outcome what the body returned → retry() now
- Outcome what the body returned → retry_after later
- retry() now → The attempt cap is checked first
- retry_after later → The attempt cap is checked first
- The attempt cap is checked first → Below the cap: requeued, or a copy to the retry address
- The attempt cap is checked first → At the cap: a copy to the dead letter
- The attempt cap is checked first → At the cap, no dead letter: rejected
- After settling: and_after and hooks run
A handler's outcome is a value. Ok
acknowledges, and an error outcome says how to settle. A plain Result<(), E> that fails is
dropped, not retried.
A payload that does not decode and a handler that panics go through the
failure policy. A policy other than fail_fast
settles the delivery like the outcome of the same name, and skip acknowledges it. fail_fast
stops the service and leaves the delivery unsettled, so a broker that redelivers hands it back after
the restart.
An immediate retry() with no attempt
cap and no dead letter declared is the broker's own
requeue. Under a declaration, a broker that counts its redeliveries still requeues, and the count is
the broker's. On a broker that counts nothing, the runtime publishes a copy to the subscription's
retry address instead and drops the original. The
copy carries its attempt count in a header.
A delayed retry_after waits on the broker's
own delayed redelivery where it has one. Elsewhere the runtime publishes the copy after the delay,
with or without a declaration.
A declared cap is checked before either retry. At the cap, a delivery with a declared dead letter is copied there, and one without is rejected. A broker that moves a spent delivery itself receives the declaration at startup and applies it on its own.
A settlement that the broker refuses is logged, and the loop moves on.