Over a million developers have joined DZone.

EasyNetQ: A Breaking Change, IPublishChannel

· Integration Zone

Build APIs from SQL and NoSQL or Salesforce data sources in seconds. Read the Creating REST APIs white paper, brought to you in partnership with CA Technologies.

EasyNetQ is my high-level .NET API for RabbitMQ.

Until recently, to publish a message using EasyNetQ you would create an instance of IBus and then call the publish method on it:


The IBus instance is the logical representation of a connection to a RabbitMQ server. Generally you should open a connection to the RabbitMQ server when your service (or application) starts and close it when the service shuts down. AMQP (the messaging protocol that RabbitMQ implements) multiplexes operations over the connection using channels, so while the connection is open, multiple channels can be opened and closed to carry out AMQP operations.

Initially I’d hoped to hide channels from EasyNetQ users. With subscriptions this makes sense - after the client creates a subscription, EasyNetQ looks after the channel and the subscription consuming thread. But publishing turned out to be more complex. Channels cannot be shared between threads, so EasyNetQ initially used a ThreadLocal channel for all publish calls. A new thread meant a new channel.

This problem manifested itself with a nasty operational bug we suffered. We had a service which woke up on a timer, created some threads, and published messages on them. Although the threads ended, the channels didn’t close, and each timer interval added another few open channels. After a period of time the channel count exceeded the allowed maximum and our RabbitMQ server died. Initially we considered finding some way of discovering when a thread ends and then disposing the channels based on some trigger, but after a discussion on Stack Overflow, we came around to the view that a sensible API design hands the responsibility of managing the channel lifetime to the API’s consumer (thanks to Martin James for being the main persuader).

So let me introduce you to my new friend, IPublishChannel. Instead of calling Publish directly on the IBus instance, EasyNetQ clients now have to create an instance of IPublishChannel and call its Publish method instead. IPublishChannel, as its name suggests, represents a channel. The channel is opened when it’s created, and disposed when it’s disposed.

Here’s how you use it:

using (var publishChannel = bus.OpenPublishChannel())

So a little more API complexity, but a lot more transparency about how channels are created and disposed.

The request/response API has also changed to include IPublishChannel:

using (var publishChannel = bus.OpenPublishChannel())
    publishChannel.Request<TestRequestMessage, TestResponseMessage>(request, response => 
        Console.WriteLine("Got response: '{0}'", response.Text));

The EasyNetQ version has been bumped to 0.5 to reflect the breaking change.

Happy messaging!

The Integration Zone is brought to you in partnership with CA Technologies.  Use CA Live API Creator to quickly create complete application backends, with secure APIs and robust application logic, in an easy to use interface.


Published at DZone with permission of Mike Hadlow, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}