Skip to main content

Settlement

What ack, drop, retry and retry_after become on ZeroMQ, which settles nothing: an ack answers Unsupported, and a retry is a copy the service publishes.

Each outcome of a handler on ZeroMQ: what the delivery answers and what becomes of the messageHandlerDeliveryMessageack()AckError::Unsupporteddone: thereis nothingto settleretry()AckError::Unsupportedgone, unlessa cap is declared:then a copyretry_after(d)a copyafter dthe copy is anew message,counteddrop()AckError::UnsupportedgoneDelivery is at most once: a message the handlerdoes not finish is not delivered again
The diagram as text
  1. Handler: ack(); retry(); retry_after(d); drop()
  2. Delivery: AckError:: Unsupported; AckError:: Unsupported; a copy after d; AckError:: Unsupported
  3. Message: done: there is nothing to settle; gone, unless a cap is declared: then a copy; the copy is a new message, counted; gone
  4. ack() → AckError:: Unsupported
  5. AckError:: Unsupported → done: there is nothing to settle
  6. retry() → AckError:: Unsupported
  7. AckError:: Unsupported → gone, unless a cap is declared: then a copy
  8. retry_after(d) → a copy after d
  9. a copy after d → the copy is a new message, counted
  10. drop() → AckError:: Unsupported
  11. AckError:: Unsupported → gone
  12. Delivery is at most once: a message the handler does not finish is not delivered again

A ZeroMQ socket hands a message over and forgets it. There is no acknowledgement in the protocol, so ack and nack on a ZmqMessage answer AckError::Unsupported at once. The runtime logs that answer as a warning, and the message is done either way.

A plain retry() delivers nothing again, and the handler is not called a second time. A registration that declares max_attempts or a dead-letter destination turns retry() into a copy, as for retry_after.

ZeroMQ counts no deliveries, so redelivery_count is empty and the runtime counts the attempts itself. The count travels in the copy's x-ruststream-retry-count header, and the first delivery counts as one.

Retries​

A retry on ZeroMQ: the attempt cap decides between a copy, the dead-letter destination and a dropA deliveryx-ruststream-retry-count says which attempt it isThe handler returnsretry_after(delay), or retry() under a capmax_attempts: is this attempt below the cap?Bound:a copy toits ownlistenerDialing orresponder:a copy toa named placeAt the cap:a copy tothe dead-letter nameAt the cap,no deadletter:droppedThe copy is a newmessage, one more attemptA copy waits for its delay inside the process:a crash before the timer fires loses it
The diagram as text
  1. A delivery x-ruststream-retry-count says which attempt it is → The handler returns retry_after(delay), or retry() under a cap: handled
  2. The handler returns retry_after(delay), or retry() under a cap → max_attempts: is this attempt below the cap?: a retry
  3. max_attempts: is this attempt below the cap? → Bound: a copy to its own listener: below
  4. max_attempts: is this attempt below the cap? → Dialing or responder: a copy to a named place
  5. max_attempts: is this attempt below the cap? → At the cap: a copy to the dead- letter name: at the cap
  6. max_attempts: is this attempt below the cap? → At the cap, no dead letter: dropped
  7. Bound: a copy to its own listener → The copy is a new message, one more attempt
  8. Dialing or responder: a copy to a named place → The copy is a new message, one more attempt
  9. A copy waits for its delay inside the process: a crash before the timer fires loses it

A retry_after outcome waits for the delay inside the process, then publishes a copy through the registration's retry publisher. Where the copy goes depends on the pattern and on the side of the endpoint, and the type states it.

A ZmqQueue or ZmqFanout subscription that binds its endpoint reports its own name as the address. The retry publisher dials the subscription's own listener, and the copy arrives there as the next attempt. The mount site names nothing.

A subscription that dials reads from a peer that only sends. A ZmqRpc responder's name is not a destination: its publisher sends only to the identities requests carry. Neither has an address for a copy, so the mount site names where the copies go, usually a queue the service binds for itself. A router chain that names no destination does not compile, and a registration that names none is refused at startup.

At the cap, the delivery goes to the dead-letter destination through the same publisher, so the destination belongs to a publisher on another endpoint. On the endpoint a queue subscription binds, a dead letter would come back to that subscription: the publisher refuses it, and the delivery is dropped. On a bound fan-out, a dead-letter name under the subscription's prefix arrives back at it. With no dead-letter destination the delivery is dropped, with a warning.