We've got our queues configured to send dead letter messages (nack'ed messages specifically) to a dead letter exchange that routes them by their original topic to individual dead letter queues. This all works great and when messages are nack'ed they're sent to the correct dead letter queue.
The trouble comes in when we shovel those messages back from the dlq to the normal queue, where they get nack'ed again. For some reason, this second time through they just disappear instead of being sent back to the dead letter exchange.
I assume there's some sort of "circular message routing" detection going on, but can't find anything like that. Inspecting the messages the second time through gives all the expected headers so I'm not sure what such a thing could even be based on. Any suggestions of where to look next or if rabbit has such a thing would be greatly appreciated!
If it's necessary, our consumers are written in python using the pika library for communication.
Assuming that you have the following queues/exchanges:
global_exchange
- your main exchangeDLX
- another exchange specifically for dead-lettersqueue
- your main queue within global_exchange
. Contains arguments=x-dead-letter-exchange: 'DLX'
queue.dlq
- your dead-letter queue within global_exchange
test_message
routing_key bound to queue
and queue.dlq
Finally, I assume that you are using the shovel plugin on the queue.dlq
management page like this, to move messages from queue.dlq
into queue
:
Here is how the routing works when you send a message with test_message
as the routing_key
to the global_exchange
:
queue
from the binding on test_message
x-dead-letter-exchange
argument sends it to DLX
with routing_key= test_message
queue.dlq
binding, that queue receives the messageWhen you use that particular management panel to shovel messages back into queue
, it uses the default exchange. This changes the routing key. So the 2nd receipt of the message has a routing key that is equal to the name of the queue you are shoveling into.
Since you do not have an x-dead-letter-routing-key
configured, the message is dead-lettered to the current routing key:
If this is not set, the message's own routing keys will be used.
So on the result of the shovel, this is how it is routed:
queue
with routing_key = queue
DLX
with routing_key = queue
queue
in DLX
, message droppedThere 2 potential workarounds:
queue.dlq
to routing_key = queue
x-dead-letter-routing-key
on queue
to always send to the same routing key on dead-letter no matter what message was originally sent to it and ensure there is a binding to it within DLX