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))))
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.