Search code examples
javascriptnode.jsrabbitmqnode-amqplib

Javascript RabbitMQ -> Pull Single Message


I'm trying to pull a single message off of rabbitmq, process it, and acknowledge that single message. I don't want it to continue after acknowledgement pulling messages off the queue. If I don't do ch.close() in the code below, it continues to pull messages after acknowledging the previous message.

Using a docker RabbitMQ instance I've set up this code (which works) but I'm curious if open/closing channels quickly are the best way to do this:

amqp.connect('amqp://guest:guest@localhost', (err, conn) => {
 conn.createChannel((err, ch) => {
  if (err) {
   console.error(err);
  } else {
   let q = 'my queue';
   ch.prefetch(1);
   ch.consume(q, data => {
    console.log(data.content.toString());
    ch.ack(data);
    ch.close();
    returnData = data;
   });
  }
 });
});

Solution

  • You can pull messages one at a time, using channel.get (see http://www.squaremobius.net/amqp.node/channel_api.html#channel_get), I find this can be useful, rather than using consume (even with prefetch). You can use a long lived channel as well for this purpose.

    var amqpChannel = null;
    
    amqp.connect('amqp://guest:guest@localhost', (err, conn) => {
        conn.createChannel((err, ch) => {
            if (err) {
                console.error(err);
            } else {
                amqpChannel = ch;
            }
        });
    });
    
    var readMessageFromQueue = function() {
        if (amqpChannel) {
            amqpChannel.get(q, data => {
                // data will be set to false if no messages are available on the queue.
                if (data) {
                    console.log(data.content.toString());
                    amqpChannel.ack(data);
                }
            });
        }
    }
    
    // Whatever interval you like..
    setInterval(readMessageFromQueue, 1000);