CodeRigor

FREE LESSON

Acknowledgements, leases & redelivery

Keep delivery tokens separate from job identity and reject stale acknowledgements at exact lease boundaries.

A consumer can receive a job, perform useful work and disappear before reporting completion. Deleting on delivery loses work if the consumer stops early. Keeping unacknowledged work forever stalls it after a failure. A delivery policy needs a way to return abandoned work to the ready state and a way to distinguish an old owner from a new one.

This build uses visibility leases. Reservation creates a delivery token and an expiry tick; the job leaves ready but remains active. Acknowledgement removes the live delivery. At the deadline, an unacknowledged delivery becomes ready again and its old token is invalid. Every reservation creates a new token, even when the job ID repeats. A token names one ownership interval; an ID names the underlying work.

One job, multiple delivery intervals
start / 3
Expiry returns work and invalidates its old delivery token.
One job, multiple delivery intervals
Expiry returns work and invalidates its old delivery token.

Take job a, reserved at tick zero with visibility five. At tick four its token is live. At tick five it is expired. An acknowledgement at five must first advance the queue's clock, then discover that the old token no longer owns anything. A later reservation of a obtains token two. Otherwise an old worker could acknowledge the new worker's delivery accidentally.

Python
deliveries = {1: {"id": "a", "deadline": 5}}
now = 5
expired = [token for token, job in deliveries.items() if job["deadline"] <= now]
ready = [deliveries.pop(token)["id"] for token in expired]
print(ready, 1 in deliveries)
Lost acknowledgement and a new owner
start / 2
The ID repeats, the delivery token does not.
Lost acknowledgement and a new owner
The ID repeats, the delivery token does not.

The model prepends expired jobs in reservation order. That choice is part of this exercise, not a universal broker ordering promise. Requeueing, priorities and multiple consumers can alter what a real application observes. A global prefetch bound limits simultaneous active deliveries here; RabbitMQ applies prefetch according to its own channel and consumer rules.

All times are arguments. Reject a backward or noninteger clock before modifying ownership. Equal ticks are legal because several operations can occur at the same logical time. A call that advances time can reclaim multiple deliveries, even when the requested token was never valid. Build tests should inspect the queue after these calls rather than assuming a false acknowledgement is globally side-effect-free.

Acknowledging after the effect allows redelivery when acknowledgement is lost. That favors retaining work but permits duplicate processing. A lease does not prove that the previous consumer has stopped: a slow consumer can continue running after expiry. Local token validation protects this queue's operations; an external database or payment provider needs its own transaction, idempotency or fencing mechanism.

RabbitMQ's ordinary manual-ack recovery is tied to channel/connection lifecycle, with delivery acknowledgement timeouts also available. Our exact-tick visibility model makes failure cases easy to test without pretending to reproduce that broker protocol. The checks, bug hunts and build establish deterministic redelivery and stale-token rejection in memory. They establish neither durable messages nor exactly-once delivery. Retry policy and effect deduplication address different parts of the problem next.

Watch & read

Free lectures, talks and readings that cover this skill from another angle. All resources →

Watch 20:30–33:50 for the consumer flow. Pause to identify receive, application work and acknowledgement. Exact visibility ticks and stale-token tests are taught by this lesson, not promised by the video.