# @title Ruby AMQP gem: Using vendor-specific AMQP extensions

h1. Vendor-specific AMQP extensions support in amqp gem

h2. RabbitMQ extensions

h2. Supported extensions

AMQP gem supports many RabbitMQ extensions to AMQP 0.9.1:

* "Publisher confirmations":http://www.rabbitmq.com/extensions.html#confirms (confirm.* class)
* "Negative acknowledgements":http://www.rabbitmq.com/extensions.html#negative-acknowledgements (basic.nack)
* "Alternate Exchanges":http://www.rabbitmq.com/extensions.html#alternate-exchange
* "Per-queue Message Time-to-Live":http://www.rabbitmq.com/extensions.html#queue-ttl
* "Queue Leases":http://www.rabbitmq.com/extensions.html#queue-leases
* "Sender-selected Distribution":http://www.rabbitmq.com/extensions.html#sender-selected-distribution
* "Validated user_id":http://www.rabbitmq.com/extensions.html#validated-user-id

h2. Enabling RabbitMQ extensions

If you are using RabbitMQ as AMQP broker and want to use these extensions, simply replace

<pre>require "amqp"</pre>

with

<pre>
require "amqp"
require "amqp/extensions/rabbitmq"
</pre>


h2. Per-queue Message Time-to-Live

Per-queue Message Time-to-Live (TTL) is a RabbitMQ extension to AMQP 0.9.1 that lets developers control for how long
a message published to a queue can live before it is discarded. A message that has been in the queue for longer than the
configured TTL is said to be dead. Dead messages will not be delivered to consumers and cannot be fetched using
*basic.get* operation ({AMQP::Queue#pop}).

Message TTL is specified using *x-message-ttl* argument on declaration. With amqp gem, you pass it to {AMQP::Queue#initialize} or
{AMQP::Channel#queue}:

<pre>
<code>
# 1000 milliseconds
channel.queue("", :arguments => { "x-message-ttl" => 1000 })
</code>
</pre>

When a published messages is routed to multiple queues, each of the queues gets a _copy of the message_. If then the message dies in
one of the queues, it has no effect on copies of the message in other queues.

h3. Example

The example below sets message TTL for a new server-named queue to be 1000 milliseconds. It then publishes several messages that
are routed to the queue and tries to fetch messages using *basic.get* AMQP method ({AMQP::Queue#pop} after 0.7 and 1.5 seconds:

<script src="https://gist.github.com/1113127.js"> </script>


h3. Learn More

See also rabbitmq.com section on "Per-queue Message TTL":http://www.rabbitmq.com/extensions.html#queue-ttl



h2. Publisher Confirms (Publisher Acknowledgements)

In some situations not a single message can be lost. The only reliable way of doing so is using confirmations.
"Publisher Confirms AMQP extension":http://www.rabbitmq.com/blog/2011/02/10/introducing-publisher-confirms/ was designed to solve the reliable publishing problem.

Publisher confirms are similar to message acknowledgements documented in the {file:docs/Queues.textile Working With Queues} guide but involve publisher and AMQP broker
instead of consumer and AMQP broker.

!https://github.com/ruby-amqp/amqp/raw/master/docs/diagrams/006_amqp_091_message_acknowledgements.png!

!https://github.com/ruby-amqp/amqp/raw/master/docs/diagrams/007_rabbitmq_publisher_confirms.png!


h3. Public API

To use publisher confirmations, first put channel into confirmation mode using {AMQP::Channel#confirm_select}:

<pre>
<code>
channel.confirm_select
</code>
</pre>

From this moment on, every message published on this channel will cause channel's _publisher index_ (message counter) to be incremented. It is possible to access
using {AMQP::Channel#publisher_index} method. To check whether channel is in the confirmation mode, use {AMQP::Channel#uses_publisher_confirmations?} predicate.

To handle AMQP broker acknowledgements, define a handler using {AMQP::Channel#on_ack}, for example:

<pre>
<code>
channel.on_ack do |basic_ack|
 puts "Received basic_ack: multiple = #{basic_ack.multiple}, delivery_tag = #{basic_ack.delivery_tag}"
end
</code>
</pre>

Delivery tag will indicate number of confirmed messages. If *multiple* attribute is true, the confirmation is for all messages up to the number
delivery tag indicates. In other words, AMQP broker may confirm just one message or a batch of them.


h3. Example

<script src="https://gist.github.com/923599.js?file=rabbitmq_publisher_confirmations_with_amqp_gem_0.8.0.rb"></script>


h3. Learn More

See also rabbitmq.com section on "Confirms aka Publisher Acknowledgements":http://www.rabbitmq.com/extensions.html#confirms




h2. basic.nack

The AMQP specification defines the basic.reject method that allows clients to reject individual, delivered messages, instructing the broker
to either discard them or requeue them. Unfortunately, basic.reject provides no support for negatively acknowledging messages in bulk.

To solve this, RabbitMQ supports the basic.nack method that provides all the functionality of basic.reject whilst also
allowing for bulk processing of messages.

h3. Public API

When RabbitMQ extensions are loaded, {AMQP::Channel#reject} method is overriden via mixin to take one additional argument: multi (defaults to false).
When it is given and is true, amqp gem will use basic.nack AMQP method instead of basic.reject, to reject multiple messages at once.
Otherwise, basic.reject is used as usual.


h3. Learn More

See also rabbitmq.com section on "Confirms aka Publisher Acknowledgements":http://www.rabbitmq.com/extensions.html#negative-acknowledgements



h2. Alternate Exchanges

Alternate Exchanges is a RabbitMQ extension to AMQP 0.9.1 that lets developers define "fallback" exchanges where unroutable messages will be sent.


h3. Public API

To specify exchange A as alternate exchange to exchange B, specify 'alternate-exchange' argument on declaration of B:

<pre>
<code>
exchange1 = channel.fanout("ops.fallback",     :auto_delete => true)
exchange2 = channel.fanout("events.collector", :auto_delete => true, :arguments => { "alternate-exchange" => "ops.fallback" })
</code>
</pre>


h3. Example

<script src="https://gist.github.com/1159091.js?file=using_alternate_exchanges.rb"></script>


h3. Learn More

See also rabbitmq.com section on "Alternate Exchanges":http://www.rabbitmq.com/extensions.html#alternate-exchange


h2. Authors

This guide was 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


<div id="disqus_thread"></div>
<script type="text/javascript">
    /* * * CONFIGURATION VARIABLES * * */
    var disqus_shortname = 'rubyamqpdocs'; // required: replace example with your forum shortname

    var disqus_developer = 0; // set to 1 on local machine for testing comments
    var disqus_identifier = 'amqp_vendor_specific_extensions';
    var disqus_url = 'http://rdoc.info/github/ruby-amqp/amqp/master/file/docs/VendorSpecificExtensions.textile';

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
</script>
