RabbitMQ in Sinatra (An addition for Micro service)

This is in continuation with Micro Services with Sinatra . Often we need RabbitMQ to queue our requests which our micro service can serve. Obviously to handle load on servers and to re-execute it if something doesn’t work.

Following gems are required in order to connect our app with RabbitMQ

gem "sneakers"

Sneaker is high-performance RabbitMQ background processing framework for Ruby.

You can install RabbitMQ on your system or you can use docker.

#docker-compose.yml

version: "3"
 services:
 rabbitmq:
     image: rabbitmq:3-management
     environment:
       RABBITMQ_ERLANG_COOKIE: "SWQOKODSQALRPCLNMEQG"
       RABBITMQ_DEFAULT_USER: "username"
       RABBITMQ_DEFAULT_PASS: "password"
       RABBITMQ_DEFAULT_VHOST: "/"
     container_name: rabbitmq
     ports:
       - 15672:15672
       - 5671-5672:5671-5672
     restart: always
     labels:
       name:
         rabbitmq
 app:
     build: .
     volumes:
       - .:/app:delegated
     depends_on:
       - rabbitmq
     container_name: app
     environment:
       RABBITMQ_URL: amqp://username:password@rabbitmq:5672


Now need to require sneaker tasks in Rakefile

...
require 'sneakers/tasks'
...

Now its time to add a worker which can perform background job. I am going to add this file in models folder following file structure explained in MVC Architecture with Sinatra

# app/my_worker.rb


class MyWorker
  include Sneakers::Worker
  from_queue 'myworker'

  def work(data)
    puts "executing at #{Time.now}"
    ack!
  end
end

Add as many worker you want. Now all workers need to be started and to do this we may need to create a startup script which list all workers.

# worker.rb

require 'bundler/setup'
require_relative 'config/environment.rb' # since all my app related setting is defined in application.rb
require 'sneakers/runner'

Sneakers.configure(:amqp => ENV['RABBITMQ_URL'], :daemonize => false, :log => STDOUT)

r = Sneakers::Runner.new([ MyWorker ])
r.run

Now start your worker by running ruby workers.rb . Since I am using docker I need to start all services with docker-compose. To start sinatra app and sneaker all together I added foreman gem to Gemfile. Add Procfile in root of project

# Procfile
web:  bundle exec rackup config.ru -s puma
worker: ruby workers.rb

Now foreman start can start web server and sneaker all together. Edit command in Dockerfile

#Dockerfile
...

EXPOSE 80
CMD ["bundle", "exec", "foreman", "start"]

Now docker-compose should work flawlessly 😀

Tips: Use Bunny gem to publish jobs to RabbitMQ from your parent app. So parent app will send jobs to RabbitMQ and your sinatra app can execute it.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s