ACK, NACK and settlement
Distinguish handler results, database commits, handoff confirmations and original broker settlement evidence.
A handler returns Result<(), QueueHandlerError> and receives no ACK or NACK object. Lily combines the pipeline result, scope cleanup and any transaction outcome to manage settlement of the original delivery. RawDelivery does not expose this authority either.
Normal decision table#
| Outcome | Framework path |
|---|---|
| Pipeline and cleanup succeed; required transaction commit completes | ACK the original delivery |
| Retryable failure with application retries remaining | Retry bucket mandatory publish → confirm → original ACK |
| Permanent failure or exhausted attempts | DLQ mandatory publish → confirm → original ACK |
| Handoff adapter error/panic/timeout | One bounded NACK/requeue within the remaining budget; preserve failure |
| Handoff confirmed, original ACK uncertain | Retain confirmation; original settlement unresolved |
| Mongo lease/ambiguous-commit deferred | Bounded requeue of the original; not a normal application retry |
This table describes paths with usable transport and remaining settlement budget. A path may fail to complete because of lost authority, cancellation or a deadline. An ordinary business failure is distinct from an infrastructure failure that prevents a safe handoff to another queue.
Confirmation and original ACK are separate evidence#
application failure
-> mandatory publish to selected retry/DLQ destination
-> publisher confirm
-> original delivery ACKHandoff confirmation means the broker accepted the publish to the selected destination. The original ACK follows. If the ACK fails or becomes uncertain, the same attempt does not repeat the handoff and does not lose the confirmation evidence. Broker redelivery of the original can still cause duplicate processing.
A handler returning Ok(()), a successful after_delivery, a database commit or a local task join is not by itself evidence of a remote ACK. Transactional inbox provides deduplication within a defined database boundary; that does not extend to global exactly-once behavior across the broker and external systems.
Poison messages and oversized bodies#
Invalid canonical envelopes or metadata bounds are rejected before the application pipeline. Do not expect extractors to access hostile raw metadata; rejection uses bounded/sanitized data. Unsupported versions or content produce permanent failure during dispatch before a scope is opened.
If the body exceeds its size limit, a non-requeueing broker NACK/dead-letter path runs before cloning it for the application. This broker-native path does not provide the same delivery evidence as the application’s mandatory publish/confirm handoff.
Force and uncertain outcomes#
A force notification does not immediately revoke settlement authority on a healthy channel. Work completing during cooperation may still be ACKed within the remaining budget. When final abort is required, authority is revoked and actual task joins are observed; unfinished settlement remains unresolved.
ACK/NACK calls for the same original delivery are not blindly repeated. Redelivered=true does not reveal whether prior work committed. Use operational diagnostics for event-level investigation and the shutdown report for lifecycle outcomes.
Sources for this page v0.1.0
This guide is based on the reviewed framework commit.