# @title Ruby AMQP gem: Patterns and Use Cases h1. Patterns and Use Cases h2. About this guide This guide explains typical messaging patterns and use cases. It only covers the most common scenarios. For comprehensive list of messaging patterns, consult books on this subject, for example, "Enterprise Integration Patterns":http://www.eaipatterns.com. This work is licensed under a Creative Commons Attribution 3.0 Unported License (including images & stylesheets). The source is available "on Github":https://github.com/ruby-amqp/amqp/tree/master/docs. h2. Covered versions This guide covers "Ruby amqp gem":http://github.com/ruby-amqp/amqp v0.8.0 and later. h2. Introduction Messaging patterns are a lot like object-oriented design patterns: they are generalized reusable solutions to specific problems. They are not recipes, however, and their exact implementation may and will vary from application to application. Just like OO design patterns, they can classified: * Message construction patterns describe form, content and purpose of messages. * Message routing patterns outline how messages can be directed from producers to consumers. * Message transformation patterns change message content or metadata. There are other, more specialized group of messaging patterns that are out of scope of this guide. This guide demonstrates implementation of several common routing patterns plus explains how built-in AMQP 0.9.1 features can be used to implement message construction and message transformation patterns. TBD h2. Request/Reply pattern h3. Description & Use cases Request/Reply is a simple way of integration when one application issues a request and another application responds to it. This pattern is often referred to as"Remote Procedure Call", even when it is not entirely correct. Request/Reply pattern is a 1:1 communication pattern. Some examples of Request/Reply pattern are: * The 1st application requests a document that the 2nd application generates or loads and returns. * End-user application issues a search request and another application returns results back. * One application requests a progress report from another application. h3. AMQP-based implementation Implementation of Request/Reply pattern on top of AMQP 0.9.1 involves two messages: a request (Req) and a response (Res). Client app generates a request identifier and sets :message_id attribute on Req. Client also uses a server-named exclusive queue to receive replies and thus sets :reply_to Req attribute to the name of that queue. Server app uses a well-known queue name to receive requests and sets :correlation_id to :message_id of the original request message (Req) to make it possible for the client to identify what request this reply is for. h4. Request message attributes
:message_id
Unique message identifier
:reply_to
Queue name server should send the response to
h4. Response message attributes
:correlation_id
Identifier of the original request message (set to request's :correlation_id)
:routing_key
Client's replies queue name (set to request's :reply_to)
h3. Code example h4. Client code

require "amqp"

EventMachine.run do
  connection = AMQP.connect
  channel    = AMQP::Channel.new(connection)

  replies_queue = channel.queue("", :exclusive => true, :auto_delete => true)
  replies_queue.subscribe do |metadata, payload|
    puts "[response] Response for #{metadata.correlation_id}: #{payload.inspect}"
  end

  # request time from a peer every 3 seconds
  EventMachine.add_periodic_timer(3.0) do
    puts "[request] Sending a request..."
    channel.default_exchange.publish("get.time",
                                     :routing_key => "amqpgem.examples.services.time",
                                     :message_id  => Kernel.rand(10101010).to_s,
                                     :reply_to    => replies_queue.name,
                                     :immediate   => true)
  end


  Signal.trap("INT") { connection.close { EventMachine.stop } }
end

h4. Server code

require "amqp"

EventMachine.run do
  connection = AMQP.connect
  channel    = AMQP::Channel.new(connection)

  requests_queue = channel.queue("amqpgem.examples.services.time", :exclusive => true, :auto_delete => true)
  requests_queue.subscribe(:ack => true) do |metadata, payload|
    puts "[requests] Got a request #{metadata.message_id}. Sending a reply..."
    channel.default_exchange.publish(Time.now.to_s,
                                     :routing_key    => metadata.reply_to,
                                     :correlation_id => metadata.message_id,
                                     :immediate      => true,
                                     :mandatory      => true)

    metadata.ack
  end


  Signal.trap("INT") { connection.close { EventMachine.stop } }
end

In the examples above messages are published with the :immediate attribute set. This is not necessary in all cases: sometimes it is OK for requests to sit in the queue without active consumers. Replies, on the other hand, assume an active consumer and existing replies queue, so if routing or immediate delivery do not succeed, server application will log returned messages. More on this in the {file:docs/Exchanges.textile Working With Exchanges} guide. h3. Related patterns * Request/Reply * Event * Scatter/Gather * Smart Proxy h2. Command pattern h3. Description & Use cases Command pattern is very similar to Request/Reply, except that there is no reply and messages are typed. For example, most modern Web applications have at least one "background task processor" that carries out a number of operations asynchronously, without sending any responses back. Command pattern usually assumes 1:1 communication. Some specific examples of Command pattern are: * Account termination in a Web app triggers information archiving (or deletion) that is done by a separate app "in the background". * After a document or profile update, a Web app sends out commands to a search indexer application. * Virtual machines control dashboard app sends virtual machine controller application a command to reboot. h3. AMQP-based implementation Implementation of Command pattern on top of AMQP 0.9.1 involves well-known durable queues. Application that issues the command then can use default exchange to publish messages to well-known services directly. Request message :type attribute then indicates command type and message body (or body and headers) carry additional information consumer needs to carry it out. h4. Request message attributes
:type
Message type, as a string. For example: gems.install or commands.shutdown
h3. Code example h4. Producer (Sender)

require "rubygems"
require "amqp"
require "yaml"

t = Thread.new { EventMachine.run }
sleep(0.5)


connection = AMQP.connect
channel    = AMQP::Channel.new(connection, :auto_recovery => true)

channel.prefetch(1)

# Acknowledgements are good for letting the server know
# that the task is finished. If the consumer doesn't send
# the acknowledgement, then the task is considered to be unfinished
# and will be requeued when consumer closes AMQP connection (because of a crash, for example).
channel.queue("amqpgem.examples.patterns.command", :durable => true, :auto_delete => false).subscribe(:ack => true) do |metadata, payload|
  case metadata.type
  when "gems.install"
    data = YAML.load(payload)
    puts "[gems.install] Received a 'gems.install' request with #{data.inspect}"

    # just to demonstrate a realistic example
    shellout = "gem install #{data[:gem]} --version '#{data[:version]}'"
    puts "[gems.install] Executing #{shellout}"; system(shellout)
    puts "[gems.install] Done"
    puts
  else
    puts "[commands] Unknown command: #{metadata.type}"
  end

  # message is processed, acknowledge it so that broker discards it
  metadata.ack
end

puts "[boot] Ready. Will be publishing commands every 10 seconds."
Signal.trap("INT") { connection.close { EventMachine.stop } }
t.join

h4. Consumer (Recipient)

require "amqp"
require "yaml"

t = Thread.new { EventMachine.run }
sleep(0.5)

connection = AMQP.connect
channel    = AMQP::Channel.new(connection)

# publish new commands every 3 seconds
EventMachine.add_periodic_timer(10.0) do
  puts "Publishing a command (gems.install)"
  payload = { :gem => "rack", :version => "~> 1.3.0" }.to_yaml

  channel.default_exchange.publish(payload,
                                   :type        => "gems.install",
                                   :routing_key => "amqpgem.examples.patterns.command")
end

puts "[boot] Ready"
Signal.trap("INT") { connection.close { EventMachine.stop } }
t.join

h3. Related patterns * Event * Request/Reply h2. Event pattern h3. Description & Use cases Event pattern is a version of the Command pattern, but with 1 or more receivers (1:N communication). The world we live in is full of events, so applications of this pattern are endless. Some specific use cases of Event pattern are * Event logging (one application asks event collector to record certain event and possibly take action) * Event propagation in MMO games * Live sport score updates * Various "push notifications" for mobile applications h3. AMQP-based implementation Because Event pattern is a 1:N communication pattern, it typically uses a fanout exchange. Event listeners then use server-named exclusive queues and all bind to that exchange. Event messages use :type message attribute to indicate event type and message body (plus, possibly, message headers) to pass event context information. More on fanout exchange type in the {file:docs/Exchanges.textile Working With Exchanges} guide. h3. Code example TBD h3. Related patterns * Command * Publish/Subscribe h2. Document Message pattern h3. Description & Use cases TBD h3. AMQP-based implementation TBD h3. Code example TBD h2. Competing Consumers pattern h3. Description & Use cases "Competing Consumers":http://www.eaipatterns.com/CompetingConsumers.html are multiple consumers that process messages from a shared queue. TBD h3. AMQP-based implementation TBD h3. Code example TBD h2. Publish/Subscribe pattern h3. Description & Use cases TBD h3. AMQP-based implementation TBD h3. Code example TBD h2. Scatter/Gather pattern h3. Description & Use cases TBD h3. AMQP-based implementation TBD h3. Code example TBD h2. Smart Proxy pattern h3. Description & Use cases TBD h3. AMQP-based implementation TBD h3. Code example TBD h2. Multistep Processing (Routing Slip) pattern h3. Description & Use cases TBD h3. AMQP-based implementation TBD h3. Code example TBD h2. Authors These guides were written by "Michael Klishin":http://twitter.com/michaelklishin and edited by "Chris Duncan":https://twitter.com/celldee h2. Tell us what you think! Please take a moment and tell us what you think about this guide "on Twitter":http://twitter.com/rubyamqp or "Ruby AMQP mailing list":http://groups.google.com/group/ruby-amqp: what was unclear? what wasn't covered? maybe you don't like guide style or grammar and spelling are incorrect? Readers feedback is key to making documentation better. If mailing list communication is not an option for you for some reason, you can "contact guides author directly":mailto:michael@novemberain.com?subject=amqp%20gem%20documentation