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):
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:
1234567
connection.on_blockeddo|reason|puts"I am blocked now. Reason: #{reason}"endconnection.on_unblockeddoputs"I am unblocked now."end
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.
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:
123456789101112131415
context"when the exchange does not exist"doit"raises an exception"doch=connection.create_channelq=ch.queue("",:auto_delete=>true)raised=nilbeginq.bind("asyd8a9d98sa73t78hd9as^&&(&@#(*^")rescueMarchHare::NotFound=>eraised=eendraised.channel_close.reply_text.should=~/no exchange/endend
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:
123456789101112
# fixed size thread pool of size 1MarchHare::ThreadPools.single_threaded# fixed size thread pool of size 16MarchHare::ThreadPools.fixed_of_size(16)# dynamically growing thread pool, will allocate new threads# as neededMarchHare::ThreadPools.dynamically_growing# in contextsubscribe(: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:
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.
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:
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:
12
# when TLS and MQTT plugin is enabledc.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
12
# when TLS and MQTT plugin is enabledc.enabled_protocols# => ["amqp", "amqp/ssl", "mqtt"]
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.
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.
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.