I am trying to set up DLX, ideally 1 for each queue. I want to migrate 5 jobs but starting with one.
I ran this line which will apply to all queues but I am not sure how to select a specific queue rabbitmqctl set_policy DLX ".*" '{"dead-letter-exchange":"all-dlx"}' --apply-to queues
.
I have the following code the send to the queue
$this->channel->exchange_declare('all-dlx', 'fanout', false, true); $args = [ 'x-dead-letter-exchange'=> 'all-dlx' ]; $this->channel->exchange_declare($exchange, 'direct', false, true, false, false, $args); //$this->channel->queue_declare($queueName, false, true, false, false, $args); //$this->channel->exchange_declare($queueName, 'fanout', false, false, false); $msg = new AMQPMessage($body ,array('delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT) ); //$this->channel->basic_publish($msg, '', $queueName); $this->channel->basic_publish($msg, $exchange);
I am forcing a failure to test the DLX.
$this->channel->queue_declare($queueName, false, true, false, false); //$this->channel->exchange_declare($queueName, 'fanout', false, false, false); //list($queue_name, ,) = $this->channel->queue_declare(""); $this->channel->queue_bind($queueName, 'cm_upload'); $this->channel->basic_qos(null, 1, null); $this->channel->basic_consume($queueName, '', false, false, false, false, $callback); //$this->channel->basic_consume($queue_name, '', false, false, false, false, $callback); while ($this->channel->is_consuming()) { try { $this->channel->wait(); $this->log->debug("waiting..."); } catch (ErrorException $e) { $this->log->error($e); } }
How can I tell if it has actually gone to the DLX and the contents of the DLX? I am using php
UPDATE
Shall I do it like this. so each queue will have a DLX queue where the dlx queue is bound to the dlx-exchange?
$this->channel->exchange_declare('all-dlx', 'fanout', false, true); $args = [ 'x-dead-letter-exchange'=> 'all-dlx' ]; $this->channel->exchange_declare($exchange, 'direct', false, true, false, false, $args); $this->channel->queue_declare($queueName, false, true, false, false, $args); // declare dlx for queue $this->channel->queue_declare("dlx-$queueName", false, true, false, false); $this->channel->queue_bind("dlx-$queueName", 'all-dlx');
How would I tell the task which dlx queue it is meant to fail to?
Advertisement
Answer
Like any other exchange, a Dead Letter Exchange doesn’t contain messages, it routes them. In fact, the exchange doesn’t even know it’s a DLX, it just receives messages; the DLX setting just tells the queue where to send undelivered messages.
So to confirm that your configuration is working:
- Create the
all-dlx
exchange as a “fanout” exchange. It doesn’t need any special parameters. - Create a queue like
dlx-test-queue
. - Create a binding from
all-dlx
todlx-test-queue
. - Configure a queue to use your new exchange as its DLX; by passing the
'x-dead-letter-exchange'
argument toqueue_declare
, or setting a policy as you show in your question. - Force a failure, e.g. by calling
basic_nack
instead ofbasic_ack
in your consumer code. - The message should be re-delivered to the
all-dlx
exchange, and routed to thedlx-test-queue
, which you can verify by looking at the number of messages in that queue in the admin console.