Ruby RabbitMQ clients blog

News and updates about various Ruby clients for RabbitMQ

Amqp 1.1.8 Is Released

TL;DR

amqp gem 1.1.8 is released to rubygems.org.

This release is 100% backwards compatible.

Changes Between 1.1.7 and 1.1.8

amq-protocol Update

Minimum amq-protocol version is now 1.9.2.

Changes Between 1.1.6 and 1.1.7

Automatic Recovery Fix

Automatic connection recovery now correctly recovers bindings again.

Contributed by Devin Christensen.

About the Author

Michael on behalf of the Ruby RabbitMQ Clients Team

Bunny 1.0.6 Is Released

TL;DR

Bunny 1.0.6 is released to rubygems.org.

This is a bug fix release. We encourage all Bunny users to upgrade to it.

Changes between Bunny 1.0.5 and 1.0.6

Better Exception Handling in Consumers

Consumer work pools will now correctly catch all exceptions when dispatching submitted operations, not just Bunny::Exception subclasses.

TLS Without Peer Verification

Bunny now successfully performs TLS upgrade when peer verification is disabled.

Contribute by Jordan Curzon.

Bunny::Session#with_channel Ensures the Channel is Closed

Bunny::Session#with_channel now makes sure the channel is closed even if provided block raises an exception

Contributed by Carl Hoerberg.

Channel Number = 0 is Rejected

Bunny::Session#create_channel will now reject channel number 0.

Full change log can be found on GitHub.

About the Author

Michael on behalf of the Ruby RabbitMQ Clients Team

Amqp Gem 1.1.6 Is Released

TL;DR

amqp gem 1.1.6 is released to rubygems.org.

This release is 100% backwards compatible.

Changes Between 1.1.5 and 1.1.6

65535 Channels Per Connection

amqp gem now allows for 65535 channels per connection and not Ruby process.

Contributed by Neo developers.

Changes Between 1.1.4 and 1.1.5

channel.close is Delayed Until After Channel is Open

This eliminates a race condition in some codebases that use very short lived channels.

Contributed by Neo developers.

Changes Between 1.1.3 and 1.1.4

ConnectionClosedError is Back

ConnectionClosedError is now defined again.

Contributed by Carl Hörberg.

Changes Between 1.1.2 and 1.1.3

Fixed Exception in AMQP::Exchange#handle_declare_ok

AMQP::Exchange#handle_declare_ok no longer raises an exception about undefined method.

About the Author

Michael on behalf of the Ruby RabbitMQ Clients Team

March Hare 2.0.0 Is Released

TL;DR

March Hare 2.0.0 is released to rubygems.org.

This release is the final release of 2.0.

2.0 should be production ready from the stability perspective but has breaking API changes. Please consult the change log to learn about the changes.

Changes Between 1.5.0 and 2.0.0

March Hare (previously Hot Bunnies) 2.0 has breaking API changes.

New Name

March Hare is the new project name. The previous name had a sexist meaning (unintentionally) and changing it was long overdue.

exchange.unbind Support

MarchHare::Exchange#unbind is now provided to compliment MarchHare::Exchange#bind.

Safe[r] basic.ack, basic.nack and basic.reject implementation

Previously if a channel was recovered (reopened) by automatic connection recovery before a message was acknowledged or rejected, it would cause any operation on the channel that uses delivery tags to fail and cause the channel to be closed.

To avoid this issue, every channel keeps a counter of how many times it has been reopened and marks delivery tags with them. Using a stale tag to ack or reject a message will produce no method sent to RabbitMQ. Note that unacknowledged messages will be requeued by RabbitMQ when connection goes down anyway.

This involves an API change: MarchHare::Headers#delivery_tag is now and instance of a class that responds to #to_i and is accepted by MarchHare::Channel#ack and related methods.

Integers are still accepted by the same methods.

Consumer Work Pool Changes

MarchHare 1.x used to maintain a separate executor (thread pool) per non-blocking consumer. This is not optimal and reimplements the wheel RabbitMQ Java client already has invented: it dispatches consumer methods in a thread pool maintained by every connection.

Instead of maintaining its own executor, MarchHare now relies on the Java client to do the job. The key difference is that 1.x versions used to maintain a thread pool per channel while 2.x has a thread pool per connection.

It is still possible to override the executor when opening a connection by providing an executor factory (any Ruby callable):

1
2
3
MarchHare.connect(:executor_factory => Proc.new {
  MarchHare::ThreadPools.fixed_of_size(16)
})

There is a shortcut that accepts a thread pool size and takes care of the rest:

1
MarchHare.connect(:thread_pool_size => 16)

It has to be a factory to make sure we can allocate a new pool upon connection recovery, since JVM executors cannot be cloned or restarted.

By default MarchHare will rely on the default RabbitMQ Java client’s executor service, which has a fixed size of 5 threads.

Automatic Connection Recovery

MarchHare now supports automatic connection recovery from a network outage, similar to the version in Bunny.

It recovers

  • Connections
  • Shutdown hooks
  • Channels
  • Exchanges, queues and bindings declared on the connection
  • Consumers

and can be disabled by setting :automatically_recover connection option to false.

Shutdown Callbacks

MarchHare::Session#on_shutdown and MarchHare::Channel#on_shutdown are two new methods that register shutdown hooks. Those are executed when

  • Network connectivity to RabbitMQ is lost
  • RabbitMQ shuts down the connection (because of an error or management UI action)

The callbacks take two arguments: the entity that’s being shutdown (MarchHare::Session or MarchHare::Channel) and shutdown reason (an exception):

1
2
3
4
conn = MarchHare.connect
conn.on_shutdown |conn, reason|
  # ...
end

In addition, MarchHare channels will make sure consumers are gracefully shutdown (thread pools stopped, blocking consumers unblocked).

These are initial steps towards easier to use error handling and recovery, similar to what amqp gem and Bunny 0.9+ provide.

MarchHare::Channel#on_confirm

MarchHare::Channel#on_confirm provides a way to define publisher confirms callbacks. Note that it’s typically more convenient to use MarchHare::Channel#wait_for_confirms to wait for all outdated confirms.

connection.blocked, connection.unblocked Support

MarchHare::Session#on_blocked and MarchHare::Session#on_unblocked are new methods that provide a way to define blocked connection notifications callbacks:

1
2
3
4
5
6
7
connection.on_blocked do |reason|
  puts "I am blocked now. Reason: #{reason}"
end

connection.on_unblocked do
  puts "I am unblocked now."
end

Authentication Failure Notifications Support

MarchHare now supports authentication failure notifications (new in RabbitMQ 3.2).

MarchHare::Session#start

MarchHare::Session#start is a new no-op method that improves API compatibility with Bunny 0.9.

MarchHare::Queue#subscribe_with, MarchHare::Queue#build_consumer

MarchHare::Queue#subscribe_with and MarchHare::Queue#build_consumer are new method that allow using consumer objects, for example, to first instantiate a blocking consumer and pass the reference around so it can be cancelled from a different thread later.

1
2
3
4
consumer_object  = q.build_consumer(:blocking => false) do |metadata, payload|
  # ...
end
consumer         = q.subscribe_with(consumer_object, :blocking => false)

Consumer Cancellation Support

Passing a block for the :on_cancellation option to MarchHare::Queue#subscribe lets you support RabbitMQ consumer cancellation. The block should take 3 arguments: a channel, a consumer and a consumer tag.

MarchHare Operations Now Raise Ruby Exceptions

MarchHare used to expose RabbitMQ Java client’s channel implementation directly to Ruby code. This means that whenever an exception was raised, it was a Java exception (commonly java.io.IOException, wrapping a shutdown signal).

Not only this severely violates the Principle of Least Surprise, it also makes it much harder to inspect the exception and figure out how to get relevant information from it without reading the RabbitMQ Java client source.

Hot Bunnies 2.0+ provides a Ruby implementation of MarchHare::Channel which rescues Java exceptions and turns them into Ruby exceptions.

For example, handling a queue.bind failure now can be demonstrated with the following straightforward test:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
context "when the exchange does not exist" do
  it "raises an exception" do
    ch = connection.create_channel
    q  = ch.queue("", :auto_delete => true)

    raised = nil
    begin
      q.bind("asyd8a9d98sa73t78hd9as^&&(&@#(*^")
    rescue MarchHare::NotFound => e
      raised = e
    end

    raised.channel_close.reply_text.should =~ /no exchange/
  end
end

MarchHare Ruby exceptions follow AMQP 0.9.1 exception code names:

  • MarchHare::NotFound
  • MarchHare::PreconditionFailed
  • MarchHare::ResourceLocked
  • MarchHare::AccessRefused

or have otherwise meaningful names that follow Bunny names closely:

  • MarchHare::PossibleAuthenticationFailureError
  • MarchHare::ChannelAlreadyClosed

MarchHare::Queue#subscribe Now Returns a Consumer

This is a breaking API change

MarchHare::Queue#subscribe now returns a consumer (a MarchHare::Consumer instance) that can be cancelled and contains a consumer tag.

MarchHare::Subscription was eliminated as redundant. All the same methods are now available on MarchHare::Consumer subclasses.

MarchHare::Queue#subscribe Uses :block => false By Default

This is a breaking API change

MarchHare::Queue#subscribe now uses :block => false by default, thus not blocking the caller. This reduces the need to use explicitly started threads for consumers.

This is also how Bunny 0.9 works and we’ve seen this default to be a better idea.

More Convenient Way of Creating Thread Pools

MarchHare allows you to pass your own thread pool to MarchHare::Queue#subscribe via the :executor option. Choosing the right thread pool size can make a huge difference in throughput for applications that use non-blocking consumers.

Previously to 2.0, MarchHare required using Java interop and being familiar with JDK executors API to instantiate them.

MarchHare 2.0 introduces MarchHare::ThreadPools that has convenience methods that make it easier:

1
2
3
4
5
6
7
8
9
10
11
12
# fixed size thread pool of size 1
MarchHare::ThreadPools.single_threaded
# fixed size thread pool of size 16
MarchHare::ThreadPools.fixed_of_size(16)
# dynamically growing thread pool, will allocate new threads
# as needed
MarchHare::ThreadPools.dynamically_growing

# in context
subscribe(:blocking => false, :executor => MarchHare::ThreadPools.single_threaded) do |metadata, payload|
 # ...
end

RabbitMQ Java Client Upgrade

March Hare now uses RabbitMQ Java client 3.2.

Queue Predicates

MarchHare::Queue now provides several predicate methods:

  • #server_named?
  • #auto_delete?
  • #durable?
  • #exclusive?

for better Bunny 0.9+ compatibility.

About the Author

Michael on behalf of the Ruby RabbitMQ Clients Team

Bunny 1.0.5 Is Released

TL;DR

Bunny 1.0.5 is released to rubygems.org.

This is a bug fix release. We encourage all Bunny users to upgrade to it.

Changes between Bunny 1.0.4 and 1.0.5

Single Threaded Mode Fixes

Single threaded mode no longer fails with

1
undefined method `event_loop'

connection.tune.channel_max No Longer Overflows

connection.tune.channel_max could previously be configured to values greater than 216 - 1 (65535). This would result in a silent overflow during serialization. The issue was harmless in practice but is still a bug that can be quite confusing.

Bunny now caps max number of channels to 65535. This allows it to be forward compatible with future RabbitMQ versions that may allow limiting total # of open channels via server configuration.

Thread Leaks Fixes

Bunny will now correctly release heartbeat sender when allocating a new one (usually happens only when connection recovers from a network failure).

amq-protocol Update

Minimum amq-protocol version is now 1.9.0 which includes bug fixes and performance improvements for channel ID allocator.

Full change log can be found on GitHub.

About the Author

Michael on behalf of the Ruby RabbitMQ Clients Team

RabbitMQ HTTP API Client 0.9.0 Is Released

Ruby RabbitMQ HTTP API client 0.9.0 is released.

This is a minor feature release.

Changes Between 0.8.0 and 0.9.0

New Queue Binding Methods

RabbitMQ::HTTP::Client#queue_binding_info, RabbitMQ::HTTP::Client#bind_queue, and RabbitMQ::HTTP::Client#delete_queue_binding are new methods that operate on queue bindings:

1
2
3
4
5
c = RabbitMQ::HTTP::Client.new("http://guest:guest@127.0.0.1:15672")

c.bind_queue("/", "a.queue", "an.exchange", "routing.key")
c.queue_binding_info("/", "a.queue", "an.exchange", "properties.key")
c.delete_queue_binding("/", "a.queue", "an.exchange", "properties.key")

Contributed by Noah Magram.

Changes Between 0.7.0 and 0.8.0

Client#protocol_ports

RabbitMQ::HTTP::Client#enabled_protocols is a new method that returns a hash of enabled protocols to their ports. The keys are the same as returned by Client#enabled_protocols:

1
2
# when TLS and MQTT plugin is enabled
c.protocol_ports # => {"amqp" => 5672, "amqp/ssl" => 5671, "mqtt" => 1883}

Client#enabled_protocols

RabbitMQ::HTTP::Client#enabled_protocols is a new method that returns a list of enabled protocols. Some common values are:

  • amqp (AMQP 0-9-1)
  • amqp/ssl (AMQP 0-9-1 with TLS enabled)
  • mqtt
  • stomp
1
2
# when TLS and MQTT plugin is enabled
c.enabled_protocols # => ["amqp", "amqp/ssl", "mqtt"]

Full change log can be found on GitHub.

About the Author

Michael on behalf of the Ruby RabbitMQ Clients Team

Amq-protocol 1.9.0 Is Released

amq-protocol 1.9.0 is released.

This is a maintenance release that drastically improves throughput of the channel id allocator, as well as correcting some bugs in it. If you use Bunny or amqp gem, upgrading amq-protocol is highly recommended.

Changes between 1.8.0 and 1.9.0

Performance Improvements in AMQ::BitSet

AMQ::BitSet#next_clear_bit is now drastically more efficient (down from 6 minutes for 10,000 iterations to 4 seconds for 65,536 iterations).

Contributed by Doug Rohrer, Dave Anderson, and Jason Voegele from Neo.

Full change log can be found on GitHub.

About the Author

Michael on behalf of the Ruby RabbitMQ Clients Team

Bunny 1.0.4 Is Released

TL;DR

Bunny 1.0.4 is released to rubygems.org.

This is a bug fix release. We encourage all Bunny users to upgrade to it.

Changes between Bunny 1.0.3 and 1.0.4

Versioned Delivery Tag Fix

Versioned delivery tag now ensures all the arguments it operates (original delivery tag, atomic fixnum instances, etc) are coerced to Integer before comparison.

GitHub issues: #171.

Full change log can be found on GitHub.

About the Author

Michael on behalf of the Ruby RabbitMQ Clients Team

March Hare 2.0.0.rc5 Is Released

TL;DR

March Hare 2.0.0.rc5 is released to rubygems.org.

This release is a release candidate of 2.0 that focuses on usability improvements and bug fixes in automatic connection recovery.

2.0 should be production ready from the stability perspective but has breaking API changes. Please consult the change log to learn about the changes.

Changes Between 2.0.0-rc4 and 2.0.0-rc5

Connection Recovery Improvements

Automatic connection recovery has seen a few bug fixes, most notably channel recovery failures no longer terminate recovery of other channels on the same connection.

Channel recovery is now also performed in ascendant order of channel ID’s, which typically corresponds to the order in which channels were opened.

About the Author

Michael on behalf of the Ruby RabbitMQ Clients Team