RabbitMQ integration

Do you have any plans for RabbitMQ integration (similar to HangFire.SqlServer.Msmq project)? I’m implementing for my own needs by following a similar structure to HangFire.SqlServer.Msmq.

Does it have a feature like transactional queues in MSMQ to return unprocessed messages back to the queue on process termination?

Yes, RabbitMQ supports returning unprocessed messages (what they call unacknowledged messages). This can be done manually and also happens when the consumer disconnects for any reason (including process termination).

From RabbitMQ’s Broker Semantics page:

“Messages can be returned to the queue using AMQP methods that feature a requeue parameter (basic.recover, basic.reject and basic.nack), or due to a channel closing while holding unacknowledged messages. Any of these scenarios caused messages to be requeued at the back of the queue for RabbitMQ releases earlier than 2.7.0. From RabbitMQ release 2.7.0, messages are always held in the queue in publication order, even in the presence of requeueing or channel closure.”

Thanks for the detailed response. I think RabbitMQ integration will be very useful for those people who already uses it to perform message queue processing and don’t want to plug yet another technology into the project infrastructure (such as MSMQ). So, RabbitMQ integration is welcome!

How do you plan to implement this project? As a part of HangFire project or as a separate project/repository on GitHub? The former will lead to using versioning scheme of HangFire (but provide its infrastructure), but the latter will give you more independence.

@dennyferra, how RabbitMQ implementation is going on? Do you still plan to implement it? Are there any difficulties?

Sorry for the delay, Apple’s new Swift language caught my interest over the last few days :slight_smile:

I have code and tests working for the most part and just pushed it up to GitHub: https://github.com/dennyferra/HangFire/tree/rabbitMQ

Still needs some improvements, a few off the top of my head:

  • UseRabbitMq(…) requires a reference to the RabbitMQ.Client library since I’m just passing their connection configuration class. Could wrap this in another class so that the dependency does not need to be added.
  • According to best practices it is better to have publishers and consumers on separate channels. However I’m not certain if that best practice applies since it was in reference to when RabbitMQ is set up to use confirms. This implementation does not use confirms (there is more overhead with confirms). I’ll need to do more reading on this.
  • RabbitMQ does not have a Peek feature. So the way that the RabbitMqJobQueueMonitor finds the enqueued jobs is to dequeue all messages without removing them from the queue (this puts the messages in an unacknowledged state). Then dispose the RabbitMqJobQueue causing the channel to close. All unacknowledged messages then get requeued in order. There may not be a way around this, but I imagine this may slightly affect performance.

All you need to run this is a default installation of RabbitMQ, you can enable the management service to monitor RabbitMQ if you’d like. Code-wise just include the HostName of where RabbitMQ exists:

<SqlServerStorage>.UseRabbitMq(conf => conf.HostName = "localhost", "default");

Swift? No! Csharp only, only C#! No thinking required1 :smile: Regarding to RabbitMQ integration – great job! The first option is good and allows to provide configuration in a regular way, the third point is the only solution, regarding to different forums.

Do you already use it? Can’t wait for pull-request for yet another supported technology :smile:

@dennyferra, how your work is going on? Have you encountered any difficulties?

All is well, fixed a few issues I ran into in regards to recreating a channel when it closes. Added a new configuration class just need to finish the unit tests for it. I should have a pull request coming today or tomorrow.

Any status on this? Is RabbitMQ targeted for ‘official’ support? I don’t see it listed in the docs (http://hangfire.io/overview.html) as supported, and posts on it in the forum are low in number and seem mostly related to problems getting it to work. Wondering if it is something I should even consider relying on for production use?

@bitmask, I haven’t enough knowledge on RabbitMQ, so I can only say that RabbitMQ development and support is driven by community (may be including you :smile:). The code is not complex – https://github.com/HangfireIO/Hangfire/tree/master/src/Hangfire.SqlServer.RabbitMq – so you can hold your own expertise.

Thanks for the reply, I will definitely consider contributing!

I worked on the original implementation and have had it running in production for a few months now. That being said there are some issues and I’ve been meaning to address them for a while now but I haven’t had the chance yet. Mostly wanted to rewrite RabbitMqJobQueue: https://github.com/HangfireIO/Hangfire/blob/master/src/Hangfire.SqlServer.RabbitMq/RabbitMqJobQueue.cs

I had a naive understanding of RabbitMQ at the time. NServiceBus.RabbitMQ has a pretty robust implementation https://github.com/Particular/NServiceBus.RabbitMQ/tree/develop/src/NServiceBus.RabbitMQ

@dennyferra Thanks for the reply. I appreciate the work you put into the RabbitMQ support, and I’m glad to hear that you have it in production. BTW, on another thread I’ve been looking for cases of Hangfire being actually used in production because I need to make a case to my engineering team here. Can you share any details on your production use of the system (load characteristics, etc.)? If not, then any general comments experiences with it in production (stability, etc.) would be helpful. Thanks again.

@dennyferra Thank you for working on this. Another RabbitMQ library worth looking at is EasyNetQ, which I’ve been using in production for over a year.

Hi Denny or Fydon,

If possible, I’d like to discuss your experiences with EasyNetQ and Hangfire.