pratikvasa
pratikvasa

Reputation: 2045

In RabbitMQ is there a way to send messages to consumers at regular intervals?

We are using RabbitMQ to send notifications to users on apps. So there is a consumer that will send the notification to all the users using the app.

when we have multiple messages in the queue, we want rabbitmq to send each messages at least 1 hour apart.

So if there are 3 messages in the queue, each message will be sent an hour apart.

If there are no new messages in the queue and a new message is published, then depending on when the last message was sent to a consumer it will either hold it or send it.

Is there any direct way to do it?

Upvotes: 0

Views: 5876

Answers (4)

SaharshJ
SaharshJ

Reputation: 67

I stumbled upon your question and wanted to have same thing with 10 second interval but was unable to do so while using channel.consume() methods.

I started reading the documentation and came to know that while using prefetch, queue will wait till the message is acked or nacked before sending another one.

So as a hack I gave timeout of 10 seconds to my ack/nack functionality and although my processing gets finished my consumer doesn't receive more messages since the last is still pending the acknowledgement.

Check the documentation here.

My sample code

 if (response) {
        setTimeout(() => {
          console.log("acking now ");
          pendingImportChannel.ack(pendingImportMessage);
        }, 10000);
        console.log("Pending import message acknowledged.");
      } else {
        console.log("Rejecting message => " + JSON.stringify(pendingImportDetails));
        setTimeout(() => {
          pendingImportChannel.nack(pendingImportMessage, false, true);
        }, 10000);
      }

Points to note

  • Your prefetch value should be 1 (or number of messages you want to receive in one call)
  • Make sure you don't ack/nack independently.
  • Keep your acknowledgementStrategy as noAck: false. (feel free to experiment here)

Upvotes: 1

Sahil Sharma
Sahil Sharma

Reputation: 4217

One way could be:

  1. Schedule cron for every 5 or "x" minutes.
  2. Cron checks if there is a message in the queue, it extracts ONE messge from the queue. If notification is sent successfully, you can change the schedule of the cron to next run after 60 minutes (and after 5 or x minutes post that run). Check this link for more information on rescheduling the window scheduled tasks.
  3. Cron does nothing if there is no message in the queue.

Upvotes: 1

pratikvasa
pratikvasa

Reputation: 2045

After a lot of digging I could not find a direct way to do it.

One way to achieve this is to write a cron job that runs every 60 mins (or what ever interval is required). The cron job will call a consumer that checks if there is a message in the queue. If there is, It will accept only one message, process it and then shut down.

The only disadvantage is that if the first message comes at t0+1 then even though there were no messages process before it will wait for 60 minutes before processing the message.

If this can be improved let me know.

Upvotes: 0

cantSleepNow
cantSleepNow

Reputation: 10182

Yes, there is, it's described here. I'll just quote a one part:

To delay a message a user must publish the message with the special header called x-delay which takes an integer representing the number of milliseconds the message should be delayed by RabbitMQ.

Also another approach (before rabbitmq added delays exchange) was using a combination of dead-letter exchange and message ttl as described here for example.

Upvotes: 1

Related Questions