Closed joeshaw closed 13 years ago
The commits which switched from LPOP
to BLPOP
are 48afb8a3a8558bc77c0ee6a985decee819aaedf7 and 44dd501387e8bfe3c93f8192f3db91d375f5f8bd
Hmm, I notice from 746413954630489a5b59607a73d5eb0f97920f34 that the key is returned from the redis.blpop()
function, at least with version 2.2.2 of the redis-py library. So maybe we can require that version and not need to encode the queue name in the job if we decide to keep the BLPOP
route.
And I just went back and tested with redis-py 1.34.1, and redis.blpop()
there returned a list, not a tuple. So the current code appears to be broken with redis versions that old, but the important thing is that it always returns a sequence of the key as the first arg and the value as the second arg.
I'll try to whip up a patch that keeps the BLPOP
.
i'd love to see that patch; however, I'm leaning more towards switching back to LPOP. When listening to multiple queues, pyres should always check them in order. That way you can easily create priorities for the worker. When I get home tonight I'll try to take a closer look and see.
Ah, ok, if we do want affinity for queues listed earlier I'll omit the reordering.
(Is the above sufficient to merge it in, or should I create a pull request for it? I couldn't figure out a better way to attach the code to this issue.)
pull request would help a lot. Thanks for the patch, it looks like it's right on.
closed via pull request
Using
BLPOP
when queues are empty is considerably slower thanLPOP
because the entire timeout interval must expire before the next queue is checked.Let's say that you are checking
queue1
,queue2
, andqueue3
, and there is one job inqueue3
. The others are empty. Right now, the code does something like this:Since
queue1
is empty, it takes 5 seconds before theBLPOP
times out. Ditto forqueue2
. The job is popped offqueue3
immediately and executed, then the loop runs. Total time for the 3 queues to be traversed: 10 seconds plus the time it took the job to be performed. The second time, withqueue3
empty it will take 15 seconds. You can generalize this to interval time x number of empty queues.With
LPOP
, the code was structured like this:This meant that every time through the list of queues took 5 seconds, plus the time for the worker, regardless of the number of queues.
This could be solved by running a
BLPOP
across all the queues simultaneously and rotating the order of the queues to prevent affinity.The downside to this is that[Wrong. It does return a tuple of redis key and item; the code was just a little confused here.] If that's not an option, I think we should revert to theBLPOP
does not return which queue an item was popped off of. We would have to add this to the serialized job representation, which might cause compatibility issues between pyres versions (not to mention resque).LPOP
implementation. (FWIW, upstream resque still usesLPOP
)