2
votes

I have setup RabbitMQ and able to publish and consume messages with bunny gem from rails application instantly. How can we achieve delayed queueing with a pre-defined delay time per message while publishing to RabbitMQ exchange?

1
I am curious. Why do you want to delay the message? - dnsh
I am performing some background jobs here. And some jobs need to be performed after a specific time delay. - Ashik Salman

1 Answers

4
votes

Using RabbitMQ delayed messages exchange plugin: There is a plugin available for delayed messages, RabbitMQ delayed messages exchange plugin. This plugin adds a new exchange type to RabbitMQ and messages routed to that exchange can be delayed for a specified amount of time.

Combine TTL and DLX to delay message delivery: Another option is to combine TTL and DLX to delay message delivery. By combining these to functions we publish a message to a queue which will expire its message after the TTL and then reroute it to the exchange and with the dead-letter routing key so that they end up in a queue which we consume from.

require 'bunny'

B = Bunny.new ENV['CONNECTION_URL']
B.start

DELAYED_QUEUE='work.later'
DESTINATION_QUEUE='work.now'

def publish
  ch = B.create_channel
  # declare a queue with the DELAYED_QUEUE name
  ch.queue(DELAYED_QUEUE, arguments: {
    # set the dead-letter exchange to the default queue
    'x-dead-letter-exchange' => '',
    # when the message expires, set change the routing key into the destination queue name
    'x-dead-letter-routing-key' => DESTINATION_QUEUE,
    # the time in milliseconds to keep the message in the queue
    'x-message-ttl' => 3000
  })
  # publish to the default exchange with the the delayed queue name as routing key,
  # so that the message ends up in the newly declared delayed queue
  ch.default_exchange.publish 'message content', routing_key: DELAYED_QUEUE
  puts "#{Time.now}: Published the message"
  ch.close
end

def subscribe
  ch = B.create_channel
  # declare the destination queue
  q = ch.queue DESTINATION_QUEUE, durable: true 
  q.subscribe do |delivery, headers, body|
    puts "#{Time.now}: Got the message"
  end
end

subscribe()
publish()

sleep

As described here: https://www.cloudamqp.com/docs/delayed-messages.html