<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Kirill Shevchenko</title>
    <description>The latest articles on DEV Community by Kirill Shevchenko (@kirillshevch).</description>
    <link>https://dev.to/kirillshevch</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F71252%2F4224eff0-a5ec-40d9-bc10-0f25ad794a7a.jpg</url>
      <title>DEV Community: Kirill Shevchenko</title>
      <link>https://dev.to/kirillshevch</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kirillshevch"/>
    <language>en</language>
    <item>
      <title>Build Messaging Between Ruby/Rails Applications with ActiveMQ</title>
      <dc:creator>Kirill Shevchenko</dc:creator>
      <pubDate>Sun, 30 Jun 2019 11:03:08 +0000</pubDate>
      <link>https://dev.to/kirillshevch/build-messaging-between-ruby-rails-applications-with-activemq-4fin</link>
      <guid>https://dev.to/kirillshevch/build-messaging-between-ruby-rails-applications-with-activemq-4fin</guid>
      <description>&lt;p&gt;One of the tools that are rarely covered in the Ruby/Rails world are the message brokers (probably because they mostly written in Java). Everyone are familiar mostly with &lt;a href="https://medium.com/@kirill_shevch/how-to-make-simple-background-jobs-processing-in-rails-with-sucker-punch-9e7128f4db13" rel="noopener noreferrer"&gt;background jobs processing&lt;/a&gt;, but message brokers offer a more flexible approach to asynchronous execution. For example, you can create a message from one application and process it in another and continue executing without waiting for the response.&lt;/p&gt;

&lt;p&gt;Some benefits that you get at the architectural level: Fault Tolerance, Guaranteed delivery, Asynchronous communication(through Publish/Subscribe pattern), Loosely coupling, etc.&lt;/p&gt;

&lt;p&gt;One of the messaging brokers that I used is &lt;strong&gt;ActiveMQ&lt;/strong&gt;. ActiveMQ provides most of these features and I will consider building communication using this broker as an example.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;ActiveMQ&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Open source multi-protocol Messaging Broker.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F1%2A_E9ptw7tizFxZYFc_y-B8Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F1%2A_E9ptw7tizFxZYFc_y-B8Q.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Supports many &lt;a href="http://activemq.apache.org/cross-language-clients" rel="noopener noreferrer"&gt;Cross Language Clients and Protocols&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;High availability using shared storage (master/slave)&lt;/li&gt;
&lt;li&gt;KahaDB &amp;amp; JDBC options for persistence&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Installing&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;ActiveMQ requires Java 7 to run and to build.&lt;/p&gt;

&lt;h3&gt;
  
  
  Brew (on MacOS)
&lt;/h3&gt;

&lt;p&gt;The easier way to install &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;brew install apache-activemq
activemq start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Unix Binary Installation
&lt;/h3&gt;

&lt;p&gt;Download the latest version &lt;a href="http://activemq.apache.org/components/classic/download/" rel="noopener noreferrer"&gt;here&lt;/a&gt; and follow up the &lt;a href="http://activemq.apache.org/version-5-getting-started.html" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Docker
&lt;/h3&gt;

&lt;p&gt;Unfortunately, the ActiveMQ doesn’t have official docker image. One of me&lt;br&gt;
checked that I can recommend is &lt;a href="https://hub.docker.com/r/rmohr/activemq" rel="noopener noreferrer"&gt;https://hub.docker.com/r/rmohr/activemq&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker pull rmohr/activemq
docker run -p 61616:61616 -p 8161:8161 rmohr/activemq
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  CLI commands
&lt;/h3&gt;

&lt;p&gt;Here are three most useful commands for beginning:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;activemq start&lt;/code&gt; — Creates and starts a broker using a configuration file. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;activemq stop&lt;/code&gt; — Stops a running broker.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;activemq restart&lt;/code&gt; — Restarts a running broker.&lt;/p&gt;

&lt;p&gt;To see all the commands just call &lt;code&gt;activemq&lt;/code&gt; into terminal.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Start ActiveMQ&lt;/strong&gt;
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;activemq

INFO: Loading '/usr/local/Cellar/activemq/5.15.9/libexec//bin/env'INFO: Using java '/Library/Java/JavaVirtualMachines/jdk1.8.0_102.jdk/Contents/Home/bin/java'INFO: Starting - inspect logfiles specified in logging.properties and log4j.properties to get detailsINFO: pidfile created : '/usr/local/Cellar/activemq/5.15.9/libexec//data/activemq.pid' (pid '61388')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Monitoring ActiveMQ&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;You can monitor ActiveMQ using the Web Console by pointing your browser at &lt;code&gt;http://localhost:8161/admin&lt;/code&gt;. Default credentials: &lt;code&gt;login: admin, pass: admin&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F0%2A_Ol08RnDsDOjyiub" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F0%2A_Ol08RnDsDOjyiub"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Messaging Patterns&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The use of messaging brokers is simple and consists of only two concepts —&lt;br&gt;
&lt;strong&gt;Topics&lt;/strong&gt; and &lt;strong&gt;Queues&lt;/strong&gt;. But modern tools also provide a combination of these approaches and provide additional features such as implementations of Publish/Subscribe pattern, failover, etc. But first, let’s get to know the main concepts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Queue&lt;/strong&gt;&lt;br&gt; Queues are the base messaging pattern. They provide direct&lt;br&gt;
communication between a publisher and a subscriber. The publisher creates&lt;br&gt;
messages, while the consumer reads one after another. After a message was read, it’s gone from the Queue. &lt;strong&gt;If the queue has multiple subscribers, only one of them will get the message&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F1%2AFTuQb21kXVhqBhE3154QUg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F1%2AFTuQb21kXVhqBhE3154QUg.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Topic&lt;/strong&gt;&lt;br&gt; Topic implements one-to-many communication. Unlike a queue, every subscriber will receive a message sent by the publisher. &lt;strong&gt;And the main problem is that the message cannot be recovered for a single listener&lt;/strong&gt;(for example, if the service is disconnected from reading Topic).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F1%2Aoriu2K2G60oHaqXa_vaFMg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F1%2Aoriu2K2G60oHaqXa_vaFMg.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Virtual Topics&lt;/strong&gt;&lt;br&gt; Virtual topics combine both approaches. While the publisher sends messages to a topic, subscribers will receive a copy of the message on their own related queue.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F1%2A-uKsDe1ziGvpdxFXzX1Uyg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F1%2A-uKsDe1ziGvpdxFXzX1Uyg.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Protocols&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;ActiveMQ supports most of the communication &lt;a href="https://activemq.apache.org/protocols.html" rel="noopener noreferrer"&gt;protocols&lt;/a&gt; such as &lt;strong&gt;MQTT,&lt;br&gt;
OpenWire, REST, RSS and Atom, Stomp, WSIF, WebSocket&lt;/strong&gt; &lt;strong&gt;and XMPP.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Getting Started&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The easiest way is to start a feature review with a familiar protocol HTTP.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;REST&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;ActiveMQ implements a RESTful API to messaging which allows any web capable device to publish messages using a regular HTTP POST or GET.&lt;br&gt; &lt;br&gt; &lt;strong&gt;Publish to Queue&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -u admin:admin -d "body=order_id" http://localhost:8161/api/message/shop?type=queue
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F0%2AnEUURbVLerHWGa4K" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F0%2AnEUURbVLerHWGa4K"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Publish to Topic&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -u admin:admin -d "body=order_id” http://localhost:8161/api/message/shop?type=topic
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F0%2AbNegezcMgiCRA49L" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F0%2AbNegezcMgiCRA49L"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Integration with Ruby&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The protocol that I will consider — &lt;strong&gt;STOMP (&lt;/strong&gt;The Simple Text Oriented&lt;br&gt;
Messaging Protocol). STOMP provides an interoperable wire format so that STOMP clients can communicate with any STOMP message broker to provide easy and widespread messaging interoperability among many languages, platforms, and brokers.&lt;br&gt; &lt;br&gt; There is a great &lt;a href="https://github.com/stompgem/stomp" rel="noopener noreferrer"&gt;gem&lt;/a&gt; to work with this protocol for sending and receiving messages from a Stomp protocol compliant message queue. Includes: failover logic, SSL support.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'stomp'&lt;/span&gt;

&lt;span class="n"&gt;bundle&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Initialize Connection&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;config_hash&lt;/span&gt; 
  &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="ss"&gt;hosts: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt; 
      &lt;span class="p"&gt;{&lt;/span&gt; 
        &lt;span class="ss"&gt;login: &lt;/span&gt;&lt;span class="s1"&gt;'admin'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;passcode: &lt;/span&gt;&lt;span class="s1"&gt;'admin'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;host: &lt;/span&gt;&lt;span class="s1"&gt;'0.0.0.0'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;port: &lt;/span&gt;&lt;span class="mi"&gt;61613&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="ss"&gt;ssl: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt; 
      &lt;span class="p"&gt;}&lt;/span&gt; 
    &lt;span class="p"&gt;]&lt;/span&gt; 
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Stomp&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config_hash&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Queues&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Interface to Queues with STOMP is pretty simple. Just initialize the connection with the list of configurations and close after publishing the message.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Send a Message to Queue&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Stomp&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config_hash&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;order_id: &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;command: :paid&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/queue/user-notifications'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_json&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Receive a Message from Queue&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Stomp&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config_hash&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="no"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/queue/user-notifications'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="k"&gt;begin&lt;/span&gt;
      &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="c1"&gt;# message processing...&lt;/span&gt;
    &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;StandardError&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;
      &lt;span class="no"&gt;Raven&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;capture_exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note: Use exception handling to respond to them in time. For example, here I use &lt;a href="https://github.com/getsentry/raven-ruby" rel="noopener noreferrer"&gt;Raven&lt;/a&gt; — Sentry wrapper.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F1%2A2SBhEKXLd8QP1PbbyeGW4Q.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F1%2A2SBhEKXLd8QP1PbbyeGW4Q.jpeg"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Topics&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Topics have a similar interface to Queues. Some examples below.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Send a Message to Topic&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Stomp&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config_hash&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;order_id: &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;command: :paid&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/topic/user-notifications'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_json&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Receive a Message from Topic&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Stomp&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config_hash&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="no"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/topic/user-notifications'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="k"&gt;begin&lt;/span&gt;
      &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="c1"&gt;# message processing...&lt;/span&gt;
    &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;StandardError&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;
      &lt;span class="no"&gt;Raven&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;capture_exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Integration with Rails&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/kookster/activemessaging" rel="noopener noreferrer"&gt;ActiveMessaging&lt;/a&gt; — Attempt to bring the simplicity and elegance of rails development to the world of messaging.&lt;/p&gt;

&lt;p&gt;Add a gem to &lt;code&gt;Gemfile&lt;/code&gt; version for Rails 5+&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'activemessaging'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;github: &lt;/span&gt;&lt;span class="s1"&gt;'kookster/activemessaging'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;branch: &lt;/span&gt;&lt;span class="s1"&gt;'feat/rails5'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then execute:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bundle install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;Initializing&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;After adding ActiveMessaging the following command (to add a base class for defining listeners and polling server)&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails g active_messaging:install

  create  app/processors/application_processor.rb
  create  script/poller
    &lt;span class="nb"&gt;chmod  &lt;/span&gt;script/poller
  create  script/threaded_poller
    &lt;span class="nb"&gt;chmod  &lt;/span&gt;script/threaded_poller
  create  lib/poller.rb
  create  config/broker.yml
  gemfile  daemons
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Generate a listener&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rails g active_messaging:processor RailsQueue

  create  app/processors/rails_queue_processor.rb
  create  config/messaging.rb  
  invoke  rspec  
  create    spec/functional/rails_queue_processor_spec.rb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Processor&lt;/strong&gt;&lt;br&gt;
Here you specify which will be listened by &lt;code&gt;subscribes_to&lt;/code&gt; . When the message is published to &lt;code&gt;RailsQueue&lt;/code&gt; then &lt;code&gt;on_message&lt;/code&gt; executes with first arguments as the message body.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RailsQueueProcessor&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationProcessor&lt;/span&gt;
  &lt;span class="n"&gt;subscribes_to&lt;/span&gt; &lt;span class="ss"&gt;:rails_queue&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;on_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;debug&lt;/span&gt; &lt;span class="s1"&gt;'RailsQueueProcessor received: '&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Destination config&lt;/strong&gt;&lt;br&gt;
In initializer, we describe the destination of queue.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;ActiveMessaging&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Gateway&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;define&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;destination&lt;/span&gt; &lt;span class="ss"&gt;:rails_queue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'/queue/RailsQueue'&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Run Application&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;script/poller run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now you can publish to &lt;code&gt;RailsQueue&lt;/code&gt; and Rails instance will receive messages.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Production&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;First of all, you should think about deployment and maintenance. So, for small teams (without DevOps/SRE/System Administrator Role) I suggest look into Cloud Solutions.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;AmazonMQ&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://aws.amazon.com/amazon-mq" rel="noopener noreferrer"&gt;https://aws.amazon.com/amazon-mq&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Some features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uses Apache KahaDB as its data store. Other data stores, such as JDBC and LevelDB, aren't supported&lt;/li&gt;
&lt;li&gt;Offers low latency messaging, often as low as single digit milliseconds&lt;/li&gt;
&lt;li&gt;Persistence out of the box&lt;/li&gt;
&lt;li&gt;Backups&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No need to use extra API, just follow STOMP protocol (or any other) which Amazon provides to you.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F0%2AieuurqUK5i-UyQsA" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1600%2F0%2AieuurqUK5i-UyQsA"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;FIFO (First In, First Out)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To enable saving the order of delivery of messages, you need to add in the broker configuration &lt;a href="http://activemq.apache.org/total-ordering.html" rel="noopener noreferrer"&gt;total ordering&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;destinationPolicy&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;policyMap&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;policyEntries&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;policyEntry&lt;/span&gt; &lt;span class="na"&gt;topic=&lt;/span&gt;&lt;span class="s"&gt;"&amp;amp;gt;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="c"&gt;&amp;lt;!--
      The constantPendingMessageLimitStrategy is used to prevent
      slow topic consumers to block producers and affect other 
      consumers by limiting the number of messages that are retained
      For more information, see: 
      --&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;dispatchPolicy&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;strictOrderDispatchPolicy/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/dispatchPolicy&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/policyEntry&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/policyEntries&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/policyMap&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/destinationPolicy&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Reference
&lt;/h2&gt;

&lt;p&gt;Post related to my last talk on &lt;a href="https://www.eventbrite.com/e/ruby-wine-tickets-51645298478#" rel="noopener noreferrer"&gt;Ruby Wine#1&lt;/a&gt; about Event-Driven Architecture and Messaging Patterns for Ruby Microservices.&lt;br&gt;
&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/e9AAUy4kkek"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Slides available on &lt;a href="https://speakerdeck.com/kirillshevch/rubywine-number-1-event-driven-architecture-and-messaging-patterns-for-ruby-microservices" rel="noopener noreferrer"&gt;Speaker Deck&lt;/a&gt;.&lt;br&gt;
 &lt;iframe class="speakerdeck-iframe ltag_speakerdeck" src="https://speakerdeck.com/player/0414383a451d45afac939c0391bce2a6"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;For simple projects, the use of queues may not be justified, since adding an additional architectural layer responsible for queuing messages is not an easy task. And before use, you must weigh the pros and cons(for e.g. you are ready to spend time for support). Queuing allows you to scale the application more flexible and solve most performance problems that are not related to language, but to architecture.&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>rails</category>
      <category>architecture</category>
      <category>microservices</category>
    </item>
  </channel>
</rss>
