Settlement
What ack, drop, retry and retry_after become on AMQP 1.0: a disposition the broker acts on,
and copies the runtime publishes to the same address.
The diagram as text
- Handler: ack(); retry(); retry_after(d); drop(); no outcome before the link goes
- Disposition: accepted; modified delivery-failed; rejected, a copy after d; rejected; nothing
- Broker: done: the message leaves the queue; back on the queue, counted one more; the copy is a new message on the address; the broker's dead-letter policy decides; back on the queue when the link detaches
- ack() → accepted
- accepted → done: the message leaves the queue
- retry() → modified delivery-failed
- modified delivery-failed → back on the queue, counted one more
- retry_after(d) → rejected, a copy after d
- rejected, a copy after d → the copy is a new message on the address
- drop() → rejected
- rejected → the broker's dead-letter policy decides
- no outcome before the link goes → nothing
- nothing → back on the queue when the link detaches
- At most once, deliveries arrive settled: ack, retry and drop report AckError::Unsupported
A subscription is at least once by default. A delivery stays unsettled until the handler's outcome reaches the pump task as a disposition. A delivery that never gets one stays on the link, and the broker returns it to the queue when the link detaches or the connection drops.
A retry() sends modified with delivery-failed, never released. A release tells the broker
the delivery was not acted on, and it leaves delivery-count as it was. A handler that asks for a
retry did act on it and failed, and an attempt cap reads that count: without the increment a
message that always fails would come back forever. undeliverable-here stays false, so the
message may come back to this same subscription.
Settle::AtMostOnce settles each delivery as it
arrives.
| Outcome | At most once |
|---|---|
ack, drop | AckError::Unsupported, logged: the delivery was settled on arrival |
retry() | AckError::Unsupported; under a declared cap, a copy at once where the delivery carries no delivery-count |
retry_after(d) | a copy published to the address after d |
| no outcome | nothing: the broker already let the message go |
How many times a message has been delivered is delivery-count + 1, which
redelivery_count reports. A message this crate published has
no header section, so it carries no count, and the framework's retry-count header counts for it.
Retries
The diagram as text
- A delivery: its attempt is delivery-count + 1, or x-ruststream-retry-count on a copy → The handler returns retry() or retry_after(delay): handled
- The handler returns retry() or retry_after(delay) → max_attempts: is this attempt below the cap?: a retry
- max_attempts: is this attempt below the cap? → retry(): modified, back on the queue: below
- max_attempts: is this attempt below the cap? → retry_after: rejected, a copy after the delay
- max_attempts: is this attempt below the cap? → At the cap: a copy to the dead- letter address: at the cap
- max_attempts: is this attempt below the cap? → At the cap, no dead letter: rejected
- retry(): modified, back on the queue → Both come back to the subscription's address
- retry_after: rejected, a copy after the delay → Both come back to the subscription's address
- A copy waits for its delay inside the process: a stop before the timer fires loses it
The cap is declared at the mount site with
max_attempts, and the first delivery counts
as one. Below the cap, a retry() goes back to the broker with modified, and the broker counts
it. A copy carries no count of the broker's, so under a cap a retry() of a copy publishes the
next copy at once.
AMQP 1.0 holds no message back, so a retry_after is the
runtime's own. It rejects the delivery, waits for the delay, and publishes a copy with the
retry-count header raised by one. The copy goes to the subscription's own address, because one node
is where a receiver attaches its source and a sender its target. On a queue address the copy
competes for receivers like any other message, and on a topic address every subscription receives
it.
At the cap, the delivery is published as it arrived to the dead-letter address. With no dead-letter address declared it is rejected, and the broker's own dead-letter policy decides. A dead-letter address declared without a cap takes every retry.