When SIGINT (``Ctrl+C``) is received when inside a blocking
os.waitpid(), OSError is thrown, effectively cancelling the wait.
However, to facilitate a "warm shutdown", as we intend, Ctrl+C is
perfectly allowed and we want to keep waiting for the child. Therefore,
we perform a trick here, catching OSError, checking whether its cause
was SIGINT (errno == EINTR), and only in that case, loop to os.waitpid()
again.
The currently running task will be waited for, so it can gracefully
be finished. Further execution will be stopped.
If, during this waiting phase, Ctrl+C is hit again, the worker and the
horse will be terminated forcefully (this means work could be lost or
partially finished).
I merely refactored the internal calls. No external API changes have been made in this commit. In order to make the dequeueing methods consistent, each dequeue method now returns a Job instance, which is just a nice lightweight wrapper around the job tuple.
The Job class makes it easier to pass the method call info around, along with some possible meta information, like the queue the job originated from.
This fixes#7.
Redis' BLPOP command takes multiple queue arguments, but LPOP can only
take a single queue. Therefore, we need to loop over all queues
manually, in order, and raise an exception is no more work is available.