Cottontail
This library is a wrapper around the popular AMQP bunny gem. It is inspired by Sinatra to easily consume messages on different routing keys.
Installation
# Gemfile
gem 'cottontail'
Usage: Simple worker
When using this gem, you should already be familiar with RabbitMQ and, ideally, the Bunny gem as it is used internally. Given we place our code into worker.rb
, we can define a simple class like so:
# worker.rb
require 'cottontail'
class Worker
include Cottontail::Consumer
session ENV['RABBITMQ_URL'] do |worker, bunny|
channel = bunny.create_channel
queue = channel.queue('', durable: true)
worker.subscribe(queue, exclusive: true, ack: false)
end
consume do |delivery_info, properties, payload|
logger.info payload.inspect
end
end
# The following will start Cottontail right away. You need to be aware that it
# will enter a subscribe loop, so it will block the process. If you don't want
# that, you can start it non-blocking with `Worker.start(false)`.
Worker.start
To run it, you may start it like the following code example. However, you should use a more sophisticated solution for daemonizing your processes in a production environment. See http://www.ruby-toolbox.com/categories/daemonizing for futher inspiration.
ruby worker.rb &
Usage: Worker on multiple queues
# worker.rb
require 'cottontail'
class Worker
include Cottontail::Consumer
session ENV['RABBITMQ_URL'] do |worker, bunny|
channel = bunny.create_channel
queue_a = channel.queue('queue_a', durable: true)
worker.subscribe(queue_a, exclusive: true, ack: false)
queue_b = channel.queue('queue_b', durable: true)
worker.subscribe(queue_b, exclusive: true, ack: false)
end
consume do |delivery_info, properties, payload|
logger.info payload.inspect
end
end
Usage: Worker that consumes multiple messages and handles them differently
You are able to scope consume
blocks. Like this, you can make a worker class
a lot easier to read. The following options are available: :exchange
, :queue
and :route
.
If your worker is subscribed to messages, but has no default consume
block
defined, cottontail's logger will write a error message. However, you can always
include a fallback without any parameters.
# worker.rb
require 'cottontail'
class Worker
include Cottontail::Consumer
session ENV['RABBITMQ_URL'] do |worker, bunny|
channel = bunny.create_channel
# Creates the `topic` exchange 'cottontail-exchange', binds the
# queue 'cottontail-queue' to it and listens to any possible
# routing key ('#').
exchange = channel.topic('cottontail-exchange')
queue = channel.queue('cottontail-queue', durable: true)
.bind(exchange, routing_key: '#')
worker.subscribe(queue, exclusive: true, ack: false)
end
# This handles any message with the routing key 'message.sent'
consume route: 'message.sent' do |delivery_info, properties, payload|
logger.info 'Received via routing key `message.sent`'
end
# This handles any message with the routing key 'message.read'. Also,
# it uses the short notation (without the hash syntax).
consume 'message.read' do |delivery_info, properties, payload|
logger.info 'Received via routing key `message.read`'
end
# In case no other consume block matches the criteria, this fill be
# the fallback to any message coming in.
consume do |delivery_info, properties, payload|
logger.info 'Anything else goes here'
end
end
Copyright © Rudolf Schmidt, released under the MIT license