Search code examples
javascriptnode.jsrabbitmqamqpnode-amqplib

how to delete messages from a Queue in RabbitMQ immediately after they ve been sent


So I started using RabbitMQ and doing the Tutorials on the Website https://www.rabbitmq.com/tutorials/tutorial-one-javascript.html but i didnt 100% understand how can the aknowledge feature be set so that a Queue will delete the message immediately right after it sends the message, it doesnt matter wether the message will be consumed or not. I'm trying to make a Queue that will delete all the messages right after the sending happens

I tried the examples in the Tutorials for example the hello world example shows that the noAck property is set to true which means we are not acknowledging the messages so the Queue should actually delete those messages after they ve been sent but that's not the case because when i run send.js 3 times and then run receive.js then i ll receive 3 times hello world message which is not what i want

 // this is send.js
   var amqp = require('amqplib/callback_api');

  amqp.connect('amqp://localhost', function(error0, connection) {
  if (error0) {
    throw error0;
  }
 connection.createChannel(function(error1, channel) {
    if (error1) {
        throw error1;
    }

    var queue = 'hello';
    var msg = 'Hello World!';

    channel.assertQueue(queue, {
        durable: false
    });
    channel.sendToQueue(queue, Buffer.from(msg));

    console.log(" [x] Sent %s", msg);
});
setTimeout(function() {
    connection.close();
    process.exit(0);
}, 500);
  });

   // this is receive .js
     var amqp = require('amqplib/callback_api');

 amqp.connect('amqp://localhost', function(error0, connection) {
if (error0) {
    throw error0;
}
connection.createChannel(function(error1, channel) {
    if (error1) {
        throw error1;
    }

    var queue = 'hello';

    channel.assertQueue(queue, {
        durable: false
    });

    console.log(" [*] Waiting for messages in %s. To exit press CTRL+C", 
   queue);

    channel.consume(queue, function(msg) {
        console.log(" [x] Received %s", msg.content.toString());
    }, {
        noAck: true
    });
});
});

for example if i run 3 times send.js there is 2 cases that can happen. case 1 is that the message will be consumed from the receiver and done. case2 is that it ll be not consumed from the receiver and in this case i want it to be deleted i dont want the message to be consumed if i run receive.js after a month from send.js, but i want also my Queue to be durable and not exclusive. it ll be also a Problem when i keep calling send.js and messages will be pushed all the time in that Queue and then if i run receive.js i ll receive a 1000 message at the same time so my goal is to avoid that. I appreciate any help


Solution

  • What I think you want, after reading the comments and the question again, is that you want the message be either delivered to the consumer, or dropped if it can't be delivered at the moment it hits the queue. If this is the case, you can set the TTL to 0, either on the queue or on individual messages. From the relevant part of the documentation:

    Setting the TTL to 0 causes messages to be expired upon reaching a queue unless they can be delivered to a consumer immediately.

    To set the TTL of the queue, in your case of JavaScript client you need to modify the call to channel.assertQueue to include the arguments with x-message-ttl set to 0. Here's the example of the relevant part:

    var queue = 'hello';
    channel.assertQueue(queue, {
        durable: false,
        arguments: {
            "x-message-ttl": 0
        }
    });
    

    For more detailed information, consult the amqp.node documentation.