Ruby RabbitMQ clients blog

News and updates about various Ruby clients for RabbitMQ

Bunny 0.9.4 Is Released

TL;DR

Bunny 0.9.4 is released to rubygems.org.

This is a usability improvement release that is completely backwards compatible with 0.9.0.

We encourage all Bunny users to upgrade to it.

Changes between Bunny 0.9.3 and 0.9.4

Client TLS Certificates are Optional

Bunny will no longer require client TLS certificates. Note that CA certificate list is still necessary.

If RabbitMQ TLS configuration requires peer verification, client certificate and private key are mandatory.

Full change log can be found on GitHub.

Michael on behalf of the Ruby RabbitMQ Clients Team

Bunny 0.9.3 Is Released

TL;DR

Bunny 0.9.3 is released to rubygems.org.

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

We encourage all Bunny users to upgrade to it.

Changes between Bunny 0.9.2 and 0.9.3

Publishing Over Closed Connections

Publishing a message over a closed connection (during a network outage, before the connection is open) will now correctly result in an exception.

Contributed by Matt Campbell.

Full change log can be found on GitHub.

Michael on behalf of the Ruby RabbitMQ Clients Team

Bunny 0.9.2 Is Released

TL;DR

Bunny 0.9.2 is released to rubygems.org.

This is a stability improvement release that is completely backwards compatible with 0.9.0.

We encourage all Bunny users to upgrade to it.

Changes between Bunny 0.9.1 and 0.9.2

Reliability Improvement in Automatic Network Failure Recovery

Bunny now ensures a new connection transport (socket) is initialized before any recovery is attempted.

Changes between Bunny 0.9.0 and 0.9.1

Reliability Improvement in Bunny::Session#create_channel

Bunny::Session#create_channel now uses two separate mutexes to avoid a (very rare) issue when the previous implementation would try to re-acquire the same mutex and fail (Ruby mutexes are non-reentrant).

Full change log can be found on GitHub.

Michael on behalf of the Ruby RabbitMQ Clients Team

Bunny 0.9.0 Final Is Released

TL;DR

Bunny 0.9.0 is released to rubygems.org.

This release is a ground-up rewrite of Bunny that eliminates a lot of limitations of earlier versions, adds new features, improves throughput, makes Bunny benefit from runtime parallelism on Ruby implementations that support it and introduces other numerous improvements.

It is not entirely backwards compatible, although we’ve tried hard to make upgrading as seamless as possible.

This is a major step forward for Bunny. The library is now a feature complete, first class RabbitMQ client.

We encourage all Bunny users to upgrade to it.

Release Highlights

Feature Complete

Bunny 0.9 supports all RabbitMQ 3.x features, including extensions.

If something is possible to do with RabbitMQ over AMQP 0.9.1, you can do it with Bunny 0.9.

No More Limitations

Bunny 0.7.x and 0.8.0 did not support publishing of messages over 128 Kb in size and had limitations around asynchronous (“push”) consumers.

None of these limitations exist in 0.9.

Error Handling and Recovery

Bunny 0.9 introduces automatic recovery from network failures, much like amqp gem has.

Better Performance

Bunny 0.9 uses the same protocol serialization library as amqp gem. It has lower memory footprint and significantly more efficient: serialization throughput increased from 20% to x50 times compared to Bunny 0.8 serialization code.

Fewer memory allocations mean less GC stress and GC-induced CPU burn.

Concurrency

Bunny uses a separate thread for network activity. Consumers dispatch messages to a thread pool (by default of size 1) that can be tuned.

On Ruby runtimes that support runtime parallelism, this will increase throughput of both consumers and publishers on multicore hardware.

Improved Documentation

Bunny now has documentation guides that are on par or even better than amqp gem documentation.

Imprved TLS Support

Bunny’s TLS/SSL support is more flexible: more options available to configure when you need them.

RabbitMQ 2.x is the Minimum Supported Version

RabbitMQ 2.x is now the minimum supported version. 3.x releases are recommended.

Full Bunny 0.9 Change Log

Detailed Bunny changelog is available on GitHub.

Documentation

Guides

Documentation guides:

API Reference

Getting Help & Reporting Issues

Author

Michael on behalf of the Ruby RabbitMQ Clients Team

HotBunnies 2.0.0.pre8 Is Released

TL;DR

HotBunnies 2.0.0.pre8 is released to rubygems.org.

This release is a development milestone. 2.0 focuses on usability and introduces a couple of major API improvements and features.

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

Hot Bunnies 2.0 has breaking API changes.

Shutdown Callbacks

HotBunnies::Session#on_shutdown and HotBunnies::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 (HotBunnies::Session or HotBunnies::Channel) and shutdown reason (an exception):

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

In addition, HotBunnies 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.

HotBunnies::Session#start

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

HotBunnies::Queue#subscribe_with, HotBunnies::Queue#build_consumer

HotBunnies::Queue#subscribe_with and HotBunnies::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 HotBunnies::Queue#subscribe lets you support RabbitMQ consumer cancellation. The block should take 3 arguments: a channel, a consumer and a consumer tag.

HotBunnies Operations Now Raise Ruby Exceptions

HotBunnies 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 HotBunnies::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 HotBunnies::NotFound => e
      raised = e
    end

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

HotBunnies Ruby exceptions follow AMQP 0.9.1 exception code names:

  • HotBunnies::NotFound
  • HotBunnies::PreconditionFailed
  • HotBunnies::ResourceLocked
  • HotBunnies::AccessRefused

or have otherwise meaningful names that follow Bunny names closely:

  • HotBunnies::PossibleAuthenticationFailureError
  • HotBunnies::ChannelAlreadyClosed

HotBunnies::Queue#subscribe Now Returns a Consumer

This is a breaking API change

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

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

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

This is a breaking API change

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

RabbitMQ Java Client Upgrade

Hot Bunnies now uses RabbitMQ Java client 3.1.

Plans for 2.0.0 Final

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

  • Investigate automatic network failure recovery, like Bunny 0.9
  • Make TLS support more configurable, ideally with the same API as Bunny 0.9
  • Add logging
  • API reference documentation

Michael on behalf of the Ruby RabbitMQ Clients Team

Bunny 0.9.0.rc2 Is Released

TL;DR

Bunny 0.9.0.rc2 is released to rubygems.org.

This release fixes a couple of issues discovered since RC1. Bunny 0.9 is now feature complete and used widely enough for us to be going through the RC stage.

If you use an earlier Bunny version, please help us test 0.9 RCs!

Changes between Bunny 0.9.0.rc1 and 0.9.0.rc2

Channel Now Properly Restarts Consumer Pool

In a case when all consumers are cancelled, Bunny::Channel will shut down its consumer delivery thread pool.

It will also now mark the pool as not running so that it can be started again successfully if new consumers are registered later.

GH issue: #133.

Bunny::Queue#pop_waiting is Removed

A little bit of background: on MRI, the method raised ThreadErrors reliably. On JRuby, we used a different [internal] queue implementation from JDK so it wasn’t an issue.

Timeout.timeout uses Thread#kill and Thread#join, both of which eventually attempt to acquire a mutex used by Queue#pop, which Bunny currently uses for continuations. The mutex is already has an owner and so a ThreadError is raised.

This is not a problem on JRuby because there we don’t use Ruby’s Timeout and Queue and instead rely on a JDK concurrency primitive which provides “poll with a timeout”.

The issue with Thread#kill and Thread#raise has been first investigated and blogged about by Ruby implementers in 2008.

Finding a workaround will probably take a bit of time and may involve reimplementing standard library and core classes.

We don’t want this issue to block Bunny 0.9 release. Neither we want to ship a broken feature. So as a result, we will drop Bunny::Queue#pop_waiting since it cannot be reliably implemented in a reasonable amount of time on MRI.

Per issue #131.

More Flexible SSLContext Configuration

Bunny will now upgrade connection to SSL in Bunny::Session#start, so it is possible to fine tune SSLContext and socket settings before that:

1
2
3
4
5
6
7
8
9
require "bunny"

conn = Bunny.new(:tls                   => true,
                 :tls_cert              => "examples/tls/client_cert.pem",
                 :tls_key               => "examples/tls/client_key.pem",
                 :tls_ca_certificates   => ["./examples/tls/cacert.pem"])

puts conn.transport.socket.inspect
puts conn.transport.tls_context.inspect

This also means that Bunny.new will now open the socket. Previously it was only done when Bunny::Session#start was invoked.

Full change log can be found on GitHub.

Plans for 0.9.0 Final

There is still a few things we need to do before Bunny 0.9 final:

  • Fix any remaining important issues we get reports for
  • Make configuring low-level socket and SSL context

We will also make improvements to the documentation guides.

Michael on behalf of the Ruby RabbitMQ Clients Team

Amqp Gem 1.1.0.pre1 Is Released

TL;DR

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

This release includes one bug fix, removes more long time deprecated code and makes RabbitMQ extensions being part of the core (so they are always available, no need to load them separately).

Changes Between 1.0.0 and 1.1.0

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

Bunny 0.9.0.rc1 Is Released

TL;DR

Bunny 0.9.0.rc1 is released to rubygems.org.

This release adds TLS support and a couple of minor improvements. Bunny 0.9 is now feature complete and used widely enough for us to be confident about labelling this an RC.

Changes between Bunny 0.9.0.pre13 and 0.9.0.rc1

TLS Support

Bunny 0.9 finally supports TLS. There are 3 new options Bunny.new takes:

  • :tls which, when set to true, will set SSL context up and switch to TLS port (5671)
  • :tls_cert which is a string path to the client certificate (public key) in PEM format
  • :tls_key which is a string path to the client key (private key) in PEM format
  • :tls_ca_certificates which is an array of string paths to CA certificates in PEM format

An example:

1
2
3
4
conn = Bunny.new(:tls                   => true,
                 :tls_cert              => "examples/tls/client_cert.pem",
                 :tls_key               => "examples/tls/client_key.pem",
                 :tls_ca_certificates   => ["./examples/tls/cacert.pem"])

Bunny::Queue#pop_waiting

Bunny::Queue#pop_waiting is a new function that mimics Bunny::Queue#pop but will wait until a message is available. It uses a :timeout option and will raise an exception if the timeout is hit:

1
2
3
4
5
6
7
8
# given 1 message in the queue,
# works exactly as Bunny::Queue#get
q.pop_waiting

# given no messages in the queue, will wait for up to 0.5 seconds
# for a message to become available. Raises an exception if the timeout
# is hit
q.pop_waiting(:timeout => 0.5)

This method only makes sense for collecting Request/Reply (“RPC”) replies.

Bunny::InvalidCommand is now Bunny::CommandInvalid

Bunny::InvalidCommand is now Bunny::CommandInvalid (follows the exception class naming convention based on response status name).

Full change log can be found on GitHub.

Plans for 0.9.0 Final

There is still a few things we need to do before Bunny 0.9 final:

  • Fix any remaining important issues we get reports for
  • Make configuring low-level socket and SSL context

We will also make improvements to the documentation guides.

Michael on behalf of the Ruby RabbitMQ Clients Team

Bunny 0.9.0.pre13 Is Released

TL;DR

Bunny 0.9.0.pre13 is released to rubygems.org.

This release fixes a regression that affected consumers and a few minor usability improvements for “one-off” consumers that cancel themselves.

Changes between Bunny 0.9.0.pre12 and 0.9.0.pre13

Channels Without Consumers Now Tear Down Consumer Pools

Channels without consumers left (when all consumers were cancelled) will now tear down their consumer work thread pools, thus making HotBunnies::Queue#subscribe(:block => true) calls unblock.

This is typically the desired behavior.

Consumer and Channel Available In Delivery Handlers

Delivery handlers registered via Bunny::Queue#subscribe now will have access to the consumer and channel they are associated with via the delivery_info argument:

1
2
3
4
q.subscribe do |delivery_info, properties, payload|
  delivery_info.consumer # => the consumer this delivery is for
  delivery_info.consumer # => the channel this delivery is on
end

This allows using Bunny::Queue#subscribe for one-off consumers much easier, including when used with the :block option.

Bunny::Exchange#wait_for_confirms

Bunny::Exchange#wait_for_confirms is a convenience method on Bunny::Exchange that delegates to the method with the same name on exchange’s channel.

Plans for 0.9.0 Final

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

  • Fix any remaining important issues we get reports for
  • Finish TLS support

Michael on behalf of the Ruby RabbitMQ Clients Team

Bunny 0.9.0.pre12 Is Released

TL;DR

Bunny 0.9.0.pre12 is released to rubygems.org.

This release fixes a couple of regressions that affected publisher confirms and Ruby 1.8 compatibility.

Changes between Bunny 0.9.0.pre11 and 0.9.0.pre12

Ruby 1.8 Compatibility Regression Fix

Bunny::Socket no longer uses Ruby 1.9-specific constants.

Bunny::Channel#wait_for_confirms Return Value Regression Fix

Bunny::Channel#wait_for_confirms returns true or false again.

Plans for 0.9.0 Final

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

  • Fix any remaining important issues we get reports for
  • Finish TLS support

Michael on behalf of the Ruby RabbitMQ Clients Team