Ack — the consumer's 'you may delete' — the lease-and-ack dequeue handshake

Dequeue is two steps: the broker leases the message (in-flight, hidden from peers), and only the consumer's ack tells the broker it is safe to delete.

Previously

The broker hands each message to exactly one worker — but right now it deletes the cell at handoff. That can't be right: if the worker crashes mid-processing, the work is lost. So we split the dequeue into a lease and an ack.

Scene 05

Ack — the consumer's 'you may delete'

  1. Watch
  2. Try it
  3. Predict
  4. Capture
producerenqueueheadtailWORKERS · 3worker-1worker-2worker-3DISCARDED (rejected)
What to watch for

Watch the lease–ack handshake. The cell turns grey the moment the broker hands it to a worker; it only disappears when the worker's ack comes back. The broker is holding the cell in an 'in flight' state in between.

Continue unlocks when the animation finishes.
Implementation

Highlighted lines are the ones running in the diagram right now.

Broker.lease
pop the head, bind it to a worker, hide from peers
def lease(worker_id, auto_ack=False):
cell = queue.pop_head() # off the available strip
cell.state = 'in-flight'
cell.worker_id = worker_id # peers can't see it
in_flight[cell.id] = cell
if auto_ack:
del in_flight[cell.id] # collapse to one step
cell.state = 'acked' # gone before processing
return cell
Worker.process
do the side effect, then ack — note: ack is consumer-side
def process(cell):
try:
do_side_effect(cell.payload) # the actual work
broker.ack(self.id, cell.id) # 'you may delete'
except Exception:
# no ack sent — broker still holds the lease
# lease eventually returns to the head on crash
raise
Broker.ack
consumer→broker RPC: verify ownership, then delete
def ack(worker_id, cell_id):
cell = in_flight.get(cell_id)
if cell is None:
return # already gone / never leased
if cell.worker_id != worker_id:
raise PreconditionFailed() # not yours to ack
del in_flight[cell_id] # truly deleted now
cell.state = 'acked'

Where this sits in Build a Message Queue (RabbitMQ / SQS)

Scene 05 of 14. Dequeue is two steps: lease (hide from peers) + ack (delete). Same word as Kafka's ack, but consumer→broker direction — and auto-ack loses messages.

Up next. Ack says 'I succeeded, delete it.' What about 'I failed, don't delete it'? The consumer needs a second verdict for the error path.

All 14 scenes in Build a Message Queue (RabbitMQ / SQS) · Every curriculum

Built with Arqly
Every scene in Build a Message Queue (RabbitMQ / SQS) builds on the one before it.All 14 Build a Message Queue (RabbitMQ / SQS) scenes