Rails + RabbitMQ + ActionCable. How to build realtime microservice. (Part 2)

Clément Morisset
3 min readMay 10, 2020

--

This is the second part, here we are going to build a Consumer to receive the data send by our Producer. You can find the first part here.

Remind the design we are building:

In this part we are going to create our Dashboard app and our queue (named dashboard.restaurant).

Ok just run :

rails new Dashboard

and in you Gemfile add the following gems:

gem 'redis-rails'                                                   gem 'redis-namespace'                                                   gem 'sneakers'
gem 'bunny'

Redis: In-memory data structure store, used as a database, cache and message broker. We will use it to backed our Dashboard app.

Redis-Namespace: Redis::Namespace provides an interface to a namespaced subset of your Redis keyspace.

Sneakers: A high-performance RabbitMQ background processing framework for Ruby. It made especially for processing messages that come from queues

Bunny: Nothing new here, we used it in our Producer.

First add the Redis initializer below:

$redis = Redis::Namespace.new("dashboard:#{Rails.env}", redis: Redis.new)

First things we need to do is to connect our Dashboard (consumer) to our Crawler (producer) by creating the queue (dashboard.restaurant).

# app/lib/tasks/rabbitmq.rakenamespace :rabbitmq do
desc "Connect consumer to producer"
task :setup do
require "bunny"
conn = Bunny.new.tap(&:start) ch = conn.create_channel queue_restaurants = ch.queue("dashboard.restaurants") # bind queue to exchange
queue_restaurants.bind("crawler.restaurants")
conn.close
end
end

Add this rake task to your app. It will allow you to initialize the connection between your two app throughout RabbitMQ.

Then we need to add a restaurant worker to handle the message send by the exchange that we have created in the first part.

# app/workers/restaurants_worker.rbclass RestaurantsWorker
include Sneakers::Worker

from_queue "dashboard.restaurants", env: nil
def work(raw_restaurant)
Restaurant.push(raw_restaurant)
ack!
end
end

Here we are telling to our worker in what queue It can find the payload. Remember we binded the queue “dashboard.restaurants” with the exchange “crawler.restaurants”.

The work method allow us to retrieve our data. Then we call a Restaurant class (we will create it in a few seconds). The ack! keyword means “acknowledge”, it will notify the producer that the message has been received.

If you run in your console:

WORKERS=RestaurantsWorker bundle exec rake sneakers:run

you should see

Congrats, now you can hear the Heartbeat of your first Sneaker worker !

Now we can create our Restaurant class we called above. In models folder you can add the following code:

# app/models/restaurant.rbclass Restaurant
KEY = "restaurant"
STORE_LIMIT = 10
def self.list(limit = STORE_LIMIT)
$redis.lrange(KEY, 0, limit).map do |raw_restaurant|
JSON.parse(raw_restaurant)
end
end
def self.push(raw_restaurant)
$redis.lpush(KEY, raw_restaurant)
$redis.ltrim(KEY, 0, STORE_LIMIT-1)
end
end

Here nothing hard, we have two methods:

List: Retrieve and the last 10 items from our Redis db

Push: Just push the data (that our RestaurantWorker retrieve from queue) in our Redis.

From this part, our consumer is connected to our producer and we are able to play with data thanks to Redis.

Just run all the command below:

# dashboard cliredis-server
WORKERS=RestaurantsWorker bundle exec rake sneakers:run
rake rabbitmq:setup

Go on http://localhost:15672/ and click on Exchange -> crawler.restaurants.

Then try to create a restaurant in your Crawler app. If everything is configured correctly you should see a beautiful curve in your RabbitMQ UI.

Have you noticed ? Our exchange is binding our “dashboard.restaurants” queue. 🎉

Well, is enough for today. You can try to play with, by displaying the data sent by your producer. If you try you will notice that you have to refresh your browser to get the last data. And it’s not what we want. We want realtime.

We will see in a third part how to display our restaurant datas in real time with ActionCable.

Third part: https://medium.com/@clementrollon/rails-rabbitmq-actioncable-how-to-build-realtime-microservice-part-3-dff10522f08

That’s it, let me know if you are facing some issues.

Cheers.

--

--