Ruby RabbitMQ clients blog

News and updates about various Ruby clients for RabbitMQ

Bunny 1.0.0.rc1 Is Released

TL;DR

Bunny 1.0.0.rc1 is released to rubygems.org.

This is a release candidate for 1.0, a major milestone for Bunny. It is 100% backwards compatible with 0.10.x.

Changes between Bunny 1.0.0.pre6 and 1.0.0.rc1

amq-protocol Update

Minimum amq-protocol version is now 1.8.0 which includes a bug fix for messages exactly 128 Kb in size.

Add timeout Bunny::ConsumerWorkPool#join

Bunny::ConsumerWorkPool#join now accepts an optional timeout argument.

Plans for 1.0.0 Final

We plan to release Bunny 1.0.0 on October 29th, 2013. The library has had its soaking period in the last few months and several issues were fixed during 0.10.x releases.

It has being adopted by many commercial users and fairly mature open source projects, such as Hutch.

Now is a good time to give Bunny a try, help us improve the documentation and report any usability issues you may find.

Michael on behalf of the Ruby RabbitMQ Clients Team

Amqp Gem 1.1.0-rc1 Is Released

TL;DR

amqp gem 1.1.0.rc1 is released to rubygems.org.

This release is ready for amqp gem users to try it out. It includes a couple of usability improvements, internal code reorganization (amq-client is no longer used), amq-protocol update and more long time deprecated API elements removed.

All users are encouraged to try this new version to make upgrading to 1.1.0 easy in the future.

Changes Between 1.0.0 and 1.1.0

amq-protocol Update

Minimum amq-protocol version is now 1.8.0 which includes a bug fix for messages exactly 128 Kb in size.

AMQ::Client is Removed

amq-client has been incorporated into amqp gem. AMQ::Client and related modules are no longer available.

AMQP::Channel#confirm_select is Now Delayed

AMQP::Channel#confirm_select is now delayed until after the channel is opened, making it possible to use it with the pseudo-synchronous code style.

RabbitMQ Extensions are Now in Core

amqp gem has been targeting RabbitMQ exclusively for a while now.

RabbitMQ extensions are now loaded by default and will be even more tightly integrated in the future.

AMQP::Channel.default is Removed

AMQP::Channel.default and method_missing-based operations on the default channel has been removed. They’ve been deprecated since 0.6.

AMQP::Channel#rpc is Removed

AMQP::RPC-related code has been removed. It has been deprecated since 0.7.

AMQP::Channel.on_error is Removed

Long time deprecated AMQP::Channel.on_error is removed.

Michael on behalf of the Ruby RabbitMQ Clients Team

Rabbitmq_http_api_client 0.4.0 Is Released

Ruby RabbitMQ HTTP API client 0.4.0 is released.

This is a minor feature release that changes the way 4xx and 5xx responses are handled.

Changes Between 0.3.0 and 0.4.0

Meaningful Exceptions for 4xx and 5xx Responses

4xx and 5xx responses now will result in meaningful exceptions being raised. For example, 404 responses will raise Faraday::Error::ResourceNotFound.

Full change log can be found on GitHub.

Michael on behalf of the Ruby RabbitMQ Clients Team

Amq-protocol 1.8.0 Is Released

amq-protocol 1.8.0 is released.

This is a bug fix release. If you use Bunny or amqp gem, upgrading amq-protocol is highly recommended.

Changes between 1.7.0 and 1.8.0

Body Framing Fix

Messages exactly 128 Kb in size had one extra (empty) body frame.

Contributed by Nicolas Viennot.

Full change log can be found on GitHub.

Michael on behalf of the Ruby RabbitMQ Clients Team

Bunny 0.10.7 Is Released

TL;DR

Bunny 0.10.7 is released to rubygems.org.

This is a usability release that is completely backwards compatible with 0.10.x. We encourage all Bunny users to upgrade to it.

Changes between Bunny 0.10.6 and 0.10.7

Add timeout Bunny::ConsumerWorkPool#join

Bunny::ConsumerWorkPool#join now accepts an optional timeout argument.

Full change log can be found on GitHub.

Michael on behalf of the Ruby RabbitMQ Clients Team

March Hare 2.0.0.rc2 Is Released

TL;DR

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

This release is a release candidate of 2.0 that introduces one usability improvement.

2.0 should be production ready from the stability perspective but has breaking API changes. Please consult the change log below before considering upgrading.

Changes Between 2.0.0-rc1 and 2.0.0-rc2

Idempotent MarchHare::Consumer#cancel

MarchHare::Consumer#cancel is now idempotent.

Michael on behalf of the Ruby RabbitMQ Clients Team

March Hare 2.0.0.rc1 Is Released

TL;DR

March Hare 2.0.0.rc1 is released to rubygems.org. With this release, the project changes name from Hot Bunnies (an unfortunate original name that has a sexist meaning) to March Hare.

This release is a release candidate of 2.0.

2.0 should be production ready from the stability perspective but has breaking API changes. Please consult the change log below before considering upgrading.

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.

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)
})

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::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

Hot Bunnies now uses RabbitMQ Java client 3.1.

Queue Predicates

MarchHare::Queue now provides several predicate methods:

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

for better Bunny 0.9+ compatibility.

Michael on behalf of the Ruby RabbitMQ Clients Team

Bunny 0.10.6 Is Released

TL;DR

Bunny 0.10.6 is released to rubygems.org.

This is a bug fix release that is completely backwards compatible with 0.10.x. We encourage all Bunny users to upgrade to it.

Changes between Bunny 0.10.5 and 0.10.6

Respect RABBITMQ_URL value

RABBITMQ_URL env variable will now have effect even if Bunny.new is invoked without arguments.

Full change log can be found on GitHub.

Michael on behalf of the Ruby RabbitMQ Clients Team

HotBunnies 2.0.0.pre13 Is Released

TL;DR

HotBunnies 2.0.0.pre13 is released to rubygems.org.

This release is a development milestone. 2.0.0.pre13 focuses on improving network connection recovery.

2.0 should be production ready from the stability perspective but has breaking API changes. Please consult the change log below before considering upgrading.

Changes Between 2.0.0.pre12 and 2.0.0.pre13

Continuous Reconnection

HotBunnies will now continuously try to reconnect after network failure (every N seconds at the moment, no exponential backoff).

Plans for 2.0.0 Final

There is still a few things we need to do before HotBunnies 2.0 can be declared complete:

  • Add logging
  • Review API reference documentation

Michael on behalf of the Ruby RabbitMQ Clients Team

Bunny 0.10.5 Is Released

TL;DR

Bunny 0.10.5 is released to rubygems.org.

This is a bug fix release that is completely backwards compatible with 0.10.x.

We encourage all Bunny users to upgrade to it.

Changes between Bunny 0.10.4 and 0.10.5

Ruby 1.8 Compatibility

Bunny is Ruby 1.8-compatible again and no longer references RUBY_ENGINE.

Bunny::Session.parse_uri

Bunny::Session.parse_uri is a new method that parses connection URIs into hashes that Bunny::Session#initialize accepts.

1
Bunny::Session.parse_uri("amqp://user:pwd@broker.eng.megacorp.local/myapp_qa")

Full change log can be found on GitHub.

Michael on behalf of the Ruby RabbitMQ Clients Team