Monday, June 04, 2012

EasyNetQ: Introducing the Advanced API

EasyNetQ is an easy to use .NET API for RabbitMQ. Check out our new homepage at easynetq.com.
EasyNetQ's mission is to provide the simplest possible API for RabbitMQ based messaging. The core IBus interface purposefully avoids exposing AMQP concepts such as exchanges, bindings, and queues; instead you get a Publish method and a Subscribe method, and a Request method and a Respond method, simple to use bus also a rather opinionated take on the most common messaging patterns.
For users who understand AMQP and want the flexibility to create their own exchange-binding-queue topology this can be quite limiting; you still want to use EasyNetQ’s connection management, subscription handling, serialization, and error handling, but you want to do something outside of EasyNetQ’s pub/sub request/response patterns. For these users we’ve provided the ‘advanced’ API.
The advanced API is implemented with the IAdvancedBus interface. An instance of this interface can be accessed via the Advanced property of IBus:
var advancedBus = RabbitHutch.CreateBus("host=localhost").Advanced;

Yes, I stole that idea from RavenDb, thanks Ayende  :)
To create a bespoke exchange-binding-queue topology use the classes in the EasyNetQ.Topology namespace. In this example I’m binding a durable queue to a direct exchange:
var queue = Queue.DeclareDurable("my.queue.name");
var exchange = Exchange.DeclareDirect("my.exchange.name");
queue.BindTo(exchange, "my.routing.key");

Once you’ve defined your topology, you can use the Publish and Subscribe methods on the IAdvancedBus. To publish, first create a new message. Note we have a new Message<T> class that exposes the AMQP basic properties:
var myMessage = new MyMessage {Text = "Hello from the publisher"};
var message = new Message<MyMessage>(myMessage);
message.Properties.AppId = "my_app_id";
message.Properties.ReplyTo = "my_reply_queue";

Now we can publish our message to the exchange that we declared above:
using (var channel = advancedBus.OpenPublishChannel())
{
    channel.Publish(exchange, routingKey, message);
}

Here’s how we subscribe to the queue we defined:
advancedBus.Subscribe<MyMessage>(queue, (msg, messageReceivedInfo) => 
    Task.Factory.StartNew(() =>
    {
        Console.WriteLine("Got Message: {0}", msg.Body.Text);
        Console.WriteLine("ConsumerTag: {0}", messageReceivedInfo.ConsumerTag);
        Console.WriteLine("DeliverTag: {0}", messageReceivedInfo.DeliverTag);
        Console.WriteLine("Redelivered: {0}", messageReceivedInfo.Redelivered);
        Console.WriteLine("Exchange: {0}", messageReceivedInfo.Exchange);
        Console.WriteLine("RoutingKey: {0}", messageReceivedInfo.RoutingKey);
    }));

Note that we also get an IMessageReceivedInfo instance that gives us information about the message context, such as the exchange, the routing key and the redelivered flag.
So as you can see, you get a lot more control and access to various AMQP entities, but still with much less complexity than using the RabbitMQ .NET C# client directly.
For more on the advanced API check out the EasyNetQ documentation. Happy messaging!

3 comments:

Anonymous said...

Great stuff Mike!

cyrus said...

Hi Mike,

Having fun with the client. Especially the new Advanced mode. Would you be interested in accepting patches to support (among other things) federated exchanges ? The Advanced API for creating exchanges doesn't accept many of the parameters available via the RabbitMQ client.

Mike Hadlow said...

Hi Cyrus,

Glad you like it. Yes I'd be very interested in getting pull requests for EasyNetQ, especially the advanced API.

For future reference, we now have a Google Group for EasyNetQ discussions. I'd encourage anyone with questions about EasyNetQ to post them there.

https://groups.google.com/forum/?fromgroups#!forum/easynetq