@ -1,7 +1,6 @@
import uuid
import uuid
from pickle import loads , dumps
from pickle import loads , dumps
from . proxy import conn
from . proxy import conn
from . exceptions import NoMoreWorkError
class DelayedResult ( object ) :
class DelayedResult ( object ) :
def __init__ ( self , key ) :
def __init__ ( self , key ) :
@ -17,15 +16,44 @@ class DelayedResult(object):
self . _rv = loads ( rv )
self . _rv = loads ( rv )
return self . _rv
return self . _rv
class Job ( object ) :
""" A Job is just a convenient datastructure to pass around job (meta) data.
"""
def to_queue_key ( queue_name ) :
@classmethod
return ' rq: %s ' % ( queue_name , )
def unpickle ( cls , pickle_data ) :
job_tuple = loads ( pickle_data )
return Job ( job_tuple )
def __init__ ( self , job_tuple , origin = None ) :
self . func , self . args , self . kwargs , self . rv_key = job_tuple
self . origin = origin
def perform ( self ) :
""" Invokes the job function with the job arguments.
"""
return self . func ( * self . args , * * self . kwargs )
class Queue ( object ) :
class Queue ( object ) :
redis_queue_namespace_prefix = ' rq: '
@classmethod
def from_queue_key ( cls , queue_key ) :
""" Returns a Queue instance, based on the naming conventions for naming
the internal Redis keys . Can be used to reverse - lookup Queues by their
Redis keys .
"""
prefix = cls . redis_queue_namespace_prefix
if not queue_key . startswith ( prefix ) :
raise ValueError ( ' Not a valid RQ queue key: %s ' % ( queue_key , ) )
name = queue_key [ len ( prefix ) : ]
return Queue ( name )
def __init__ ( self , name = ' default ' ) :
def __init__ ( self , name = ' default ' ) :
prefix = self . redis_queue_namespace_prefix
self . name = name
self . name = name
self . _key = to_queue_key ( name )
self . _key = ' %s %s ' % ( prefix , name )
@property
@property
def key ( self ) :
def key ( self ) :
@ -52,31 +80,43 @@ class Queue(object):
return DelayedResult ( rv_key )
return DelayedResult ( rv_key )
def dequeue ( self ) :
def dequeue ( self ) :
s = conn . lpop ( self . key )
blob = conn . lpop ( self . key )
return loads ( s )
if blob is None :
return None
job = Job . unpickle ( blob )
job . origin = self
return job
@classmethod
@classmethod
def _dequeue_any ( cls , queues ) :
def _lpop_any ( cls , queue_keys ) :
# Redis' BLPOP command takes multiple queue arguments, but LPOP can
""" Helper method. You should not call this directly.
# only take a single queue. Therefore, we need to loop over all
# queues manually, in order, and return None if no more work is
Redis ' BLPOP command takes multiple queue arguments, but LPOP can only
# available
take a single queue . Therefore , we need to loop over all queues
for queue in queues :
manually , in order , and return None if no more work is available .
value = conn . lpop ( queue )
"""
if value is not None :
for queue_key in queue_keys :
return ( queue , value )
blob = conn . lpop ( queue_key )
if blob is not None :
return ( queue_key , blob )
return None
return None
@classmethod
@classmethod
def dequeue_any ( cls , queues , blocking ) :
def dequeue_any ( cls , queues , blocking ) :
queue_keys = map ( lambda q : q . key , queues )
if blocking :
if blocking :
queue , msg = conn . blpop ( queue s)
queue _key, blob = conn . blpop ( queue _key s)
else :
else :
value = cls . _dequeue_any ( queues )
redis_result = cls . _lpop_any ( queue_keys )
if value is None :
if redis_result is None :
raise NoMoreWorkError ( ' No more work. ' )
return None
queue , msg = value
queue_key , blob = redis_result
return ( queue , msg )
job = Job . unpickle ( blob )
queue = Queue . from_queue_key ( queue_key )
job . origin = queue
return job
def __str__ ( self ) :
def __str__ ( self ) :
return self . name
return self . name