I have a use case with RabbitMQ and the Sneakers gem where I have multiple Workers running to respond to several dozen queues in my project. So it's very likely that workers may be processing messages from the same queue at the same time.
With one queue in particular, though - let's call it :one_at_a_time
- I only ever want one worker to be able to process a message from the queue at any given time.
The reason I want to do this is because the worker is designed to perform the following actions:
- Look up an AR object by the passed-in ID
- Check that an attribute - let's say :worked - is set.
- If
true
, thenack!
the message. - If
false
, email a user, then set:worked
to true.
- If
This is designed so that I don't accidentally email the user twice in case two messages are created in rapid succession with the same object ID. And this design would work fine if only one worker ever listened to this queue at any given time, because the first run would go through steps 1 -> 2 -> 2, then the next run would go through steps 1 -> 2 -> 1 and would not email the user. But in testing, I found that there is the potential for a race condition where two workers will pull a message off the :one_at_a_time
queue at the same time, get past the check that :worked
is set, and both send an email.
So with all this in mind, is there a way I can limit the number of workers that listen to a queue? Thank you.
For further references, Argus9's request can be archived following the below steps:
1) You can control your worker's opts to be:
2) You need to pay attention to what you have specified in your sneakers.rb as initial parameters (as its consumed by the Sneakers::Runner at worker initialization), so be sure to have the correct params in there like:
You can also build some extra controls using the RabbitMQ API, which will enables you to check things like if is there already some message been processing?... etc what is not that easy to be archived using bunny and so. Using a very simple code like: