Skip to main content

Consumers and prefetch

A queue pushes deliveries to its consumers, each within a window of unacknowledged deliveries that its acknowledgements reopen.

A queue pushes deliveries to two consumers, each with a prefetch window of two; an ack frees a slot, and a closed channel returns its deliveriesQueue ordersmessages wait in orderConsumer 1prefetch 2:2 unacknowledgedConsumer 2prefetch 2:2 unacknowledgedbasic.ack freesa slot, and the nextdelivery is pushedChannel closed:its unacknowledgeddeliveries return,marked redeliveredThe queue spreads deliveries over its consumers in turn,skipping a consumer whose window is full
The diagram as text
  1. Queue orders messages wait in order → Consumer 1 prefetch 2: 2 unacknowledged: basic.deliver
  2. Queue orders messages wait in order → Consumer 2 prefetch 2: 2 unacknowledged: basic.deliver
  3. Consumer 1 prefetch 2: 2 unacknowledged → basic.ack frees a slot, and the next delivery is pushed
  4. Consumer 2 prefetch 2: 2 unacknowledged → Channel closed: its unacknowledged deliveries return, marked redelivered
  5. The queue spreads deliveries over its consumers in turn, skipping a consumer whose window is full

A consumer does not ask for messages. It registers with basic.consume, and the queue pushes basic.deliver frames to it. Several consumers on one queue compete: the queue gives each message to one of them, in turn.

The prefetch window is the number of deliveries a consumer may hold unacknowledged. Once the window is full, the queue pushes nothing more to that consumer until an acknowledgement frees a slot. This is how a slow handler slows the queue down instead of filling the service's memory. RabbitMQ sets the window with basic.qos, per consumer, and reads 0 as no limit.

A delivery stays the consumer's until it is settled. basic.ack removes the message from the queue. basic.reject with requeue puts it back, and without requeue the queue drops it or dead-letters it. When a channel closes with deliveries still unsettled, the queue takes them back and delivers them again with the redelivered flag set.

In this crate​

Each subscription opens a channel of its own and one consumer on it. Before the consumer starts, the subscription sends basic.qos with its window: RabbitQueue::prefetch for one queue, or LapinBroker::prefetch for every subscription that sets none. The setting is a non-zero number, so a subscription that sets neither sends no basic.qos and runs with no limit.

The window also bounds a batch. AMQP has no batch frame, so a batch handler's batch is collected on the client from what the queue has already pushed: up to the size the mount site names, or what arrived within batch_wait (50 milliseconds by default). A window smaller than the batch size caps the batch at the window.

A dropped subscription closes its channel, and RabbitMQ requeues what it held unsettled. How the runtime settles each delivery is on Settlement and retries.

The protocol rules are RabbitMQ's (consumer prefetch, consumer acknowledgements, work queues).