Skip to content
Advertisement

how to test the DLX on RabbitMQ

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

queues

detail queue

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:

  1. Create the all-dlx exchange as a “fanout” exchange. It doesn’t need any special parameters.
  2. Create a queue like dlx-test-queue.
  3. Create a binding from all-dlx to dlx-test-queue.
  4. Configure a queue to use your new exchange as its DLX; by passing the 'x-dead-letter-exchange' argument to queue_declare, or setting a policy as you show in your question.
  5. Force a failure, e.g. by calling basic_nack instead of basic_ack in your consumer code.
  6. The message should be re-delivered to the all-dlx exchange, and routed to the dlx-test-queue, which you can verify by looking at the number of messages in that queue in the admin console.
User contributions licensed under: CC BY-SA
6 People found this is helpful
Advertisement