RabbitMQ Tutorials for LFE

Message Durability

We have learned how to make sure that even if the consumer dies, the task isn't lost. But our tasks will still be lost if RabbitMQ server stops.

When RabbitMQ quits or crashes it will forget the queues and messages unless you tell it not to. Two things are required to make sure that messages aren't lost: we need to mark both the queue and messages as durable.

First, we need to make sure that RabbitMQ will never lose our queue. In order to do so, we declared it as durable:

(queue (make-queue.declare
         queue (list_to_binary queue-name)
         durable 'true))

Note that we couldn't have set our old hello queue to durable once it had already been created as non-durable. RabbitMQ doesn't allow you to redefine an existing queue with different parameters and will return an error to any program that tries to do that. So we just used a different name: task-queue.

Note that we also made this change to both the producer and the consumer code.

Now we can be sure that the task-queue queue won't be lost, even if RabbitMQ restarts. The next thing we needed to do in our quest for durability was to mark our messages as persistent - by supplying a delivery_mode property with a value 2:

(message (make-amqp_msg
           props (make-P_basic delivery_mode 2)
           payload (list_to_binary payload))))

Note on Message Persistence

Marking messages as persistent doesn't fully guarantee that a message won't be lost. Although it tells RabbitMQ to save the message to disk, there is still a short time window when RabbitMQ has accepted a message and hasn't saved it yet. Also, RabbitMQ doesn't do fsync(2) for every message -- it may be just saved to cache and not really written to the disk. The persistence guarantees aren't strong, but it's more than enough for our simple task queue. If you need a stronger guarantee then you can use publisher confirms.