1
- __version__ = '0.9'
1
+ __version__ = '0.9.1 '
2
2
3
3
from redis import Redis
4
4
import pyres .json_parser as json
@@ -18,19 +18,22 @@ def setup_logging(log_level=logging.INFO, filename=None, stream=sys.stderr):
18
18
handler = WatchedFileHandler (filename )
19
19
except :
20
20
from logging .handlers import RotatingFileHandler
21
- handler = RotatingFileHandler (filename ,maxBytes = 52428800 , backupCount = 7 )
21
+ handler = RotatingFileHandler (filename ,maxBytes = 52428800 ,
22
+ backupCount = 7 )
22
23
else :
23
- handler = logging .StreamHandler (strm = stream )
24
+ handler = logging .StreamHandler (stream )
24
25
handler .setFormatter (logging .Formatter (
25
26
'%(asctime)s %(levelname)-8s %(message)s' , '%Y-%m-%d %H:%M:%S' ))
26
27
logger .addHandler (handler )
27
28
28
29
def my_import (name ):
29
- """Helper function for walking import calls when searching for classes by string names."""
30
- mod = __import__ (name )
31
- components = name .split ('.' )
32
- for comp in components [1 :]:
33
- mod = getattr (mod , comp )
30
+ """Helper function for walking import calls when searching for classes by
31
+ string names.
32
+ """
33
+ mod = __import__ (name )
34
+ components = name .split ('.' )
35
+ for comp in components [1 :]:
36
+ mod = getattr (mod , comp )
34
37
return mod
35
38
36
39
def safe_str_to_class (s ):
@@ -63,34 +66,34 @@ def str_to_class(s):
63
66
class ResQ (object ):
64
67
"""The ResQ class defines the Redis server object to which we will
65
68
enqueue jobs into various queues.
66
-
69
+
67
70
The ``__init__`` takes these keyword arguments:
68
-
71
+
69
72
``server`` -- IP address and port of the Redis server to which you want to connect. Default is `localhost:6379`.
70
-
73
+
71
74
``password`` -- The password, if required, of your Redis server. Default is "None".
72
-
75
+
73
76
``timeout`` -- The timeout keyword is in the signature, but is unused. Default is "None".
74
-
77
+
75
78
``retry_connection`` -- This keyword is in the signature but is deprecated. Default is "True".
76
-
77
-
79
+
80
+
78
81
Both ``timeout`` and ``retry_connection`` will be removed as the python-redis client
79
- no longer uses them.
80
-
82
+ no longer uses them.
83
+
81
84
Example usage::
82
85
83
86
>>> from pyres import *
84
87
>>> r = ResQ(server="192.168.1.10:6379", password="some_pwd")
85
88
# Assuming redis is running on default port with no password
86
-
89
+
87
90
**r** is a resque object on which we can enqueue tasks.::
88
91
89
92
>>>> r.enqueue(SomeClass, args)
90
93
91
- SomeClass can be any python class with a *perform* method and a *queue*
94
+ SomeClass can be any python class with a *perform* method and a *queue*
92
95
attribute on it.
93
-
96
+
94
97
"""
95
98
def __init__ (self , server = "localhost:6379" , password = None ):
96
99
self .redis = server
@@ -144,9 +147,9 @@ def _set_redis(self, server):
144
147
redis = property (_get_redis , _set_redis )
145
148
146
149
def enqueue (self , klass , * args ):
147
- """Enqueue a job into a specific queue. Make sure the class you are passing
148
- has **queue** attribute and a **perform** method on it.
149
-
150
+ """Enqueue a job into a specific queue. Make sure the class you are
151
+ passing has **queue** attribute and a **perform** method on it.
152
+
150
153
"""
151
154
queue = getattr (klass ,'queue' , None )
152
155
if queue :
@@ -170,14 +173,14 @@ def enqueue_from_string(self, klass_as_string, queue, *args, **kwargs):
170
173
logging .debug ("job arguments: %s" % str (args ))
171
174
else :
172
175
logging .debug ("no arguments passed in." )
173
-
176
+
174
177
def queues (self ):
175
178
return self .redis .smembers ("resque:queues" ) or []
176
-
179
+
177
180
def info (self ):
178
- """Returns a dictionary of the current status of the pending jobs,
181
+ """Returns a dictionary of the current status of the pending jobs,
179
182
processed, no. of queues, no. of workers, no. of failed jobs.
180
-
183
+
181
184
"""
182
185
pending = 0
183
186
for q in self .queues ():
@@ -191,73 +194,81 @@ def info(self):
191
194
'failed' : Stat ('failed' ,self ).get (),
192
195
'servers' : ['%s:%s' % (self .redis .host , self .redis .port )]
193
196
}
194
-
197
+
195
198
def keys (self ):
196
- return [key .replace ('resque:' ,'' ) for key in self .redis .keys ('resque:*' )]
197
-
199
+ return [key .replace ('resque:' ,'' )
200
+ for key in self .redis .keys ('resque:*' )]
201
+
198
202
def reserve (self , queue ):
199
203
from pyres .job import Job
200
204
return Job .reserve (queue , self )
201
-
205
+
202
206
def __str__ (self ):
203
207
return "PyRes Client connected to %s" % self .redis .server
204
-
208
+
205
209
def workers (self ):
206
210
from pyres .worker import Worker
207
211
return Worker .all (self )
208
-
212
+
209
213
def working (self ):
210
214
from pyres .worker import Worker
211
215
return Worker .working (self )
212
-
216
+
213
217
def remove_queue (self , queue ):
214
218
if queue in self ._watched_queues :
215
219
self ._watched_queues .remove (queue )
216
220
self .redis .srem ('resque:queues' ,queue )
217
221
del self .redis ['resque:queue:%s' % queue ]
218
-
222
+
219
223
def close (self ):
220
224
"""Close the underlying redis connection.
221
-
225
+
222
226
"""
223
227
self .redis .disconnect ()
224
-
228
+
225
229
def enqueue_at (self , datetime , klass , * args , ** kwargs ):
226
230
class_name = '%s.%s' % (klass .__module__ , klass .__name__ )
227
- logging .info ("enqueued '%s' job for execution at %s" % (class_name , datetime ))
231
+ logging .info ("enqueued '%s' job for execution at %s" % (class_name ,
232
+ datetime ))
228
233
if args :
229
234
logging .debug ("job arguments are: %s" % str (args ))
230
235
payload = {'class' :class_name , 'queue' : klass .queue , 'args' :args }
231
236
if 'first_attempt' in kwargs :
232
237
payload ['first_attempt' ] = kwargs ['first_attempt' ]
233
238
self .delayed_push (datetime , payload )
234
-
239
+
235
240
def delayed_push (self , datetime , item ):
236
241
key = int (time .mktime (datetime .timetuple ()))
237
242
self .redis .rpush ('resque:delayed:%s' % key , ResQ .encode (item ))
238
243
self .redis .zadd ('resque:delayed_queue_schedule' , key , key )
239
-
244
+
240
245
def delayed_queue_peek (self , start , count ):
241
- return [int (item ) for item in self .redis .zrange ('resque:delayed_queue_schedule' , start , start + count ) or []]
242
-
246
+ return [int (item ) for item in self .redis .zrange (
247
+ 'resque:delayed_queue_schedule' , start , start + count ) or []]
248
+
243
249
def delayed_timestamp_peek (self , timestamp , start , count ):
244
250
return self .list_range ('resque:delayed:%s' % timestamp , start , count )
245
-
251
+
246
252
def delayed_queue_schedule_size (self ):
247
- return self .redis .zcard ('resque:delayed_queue_schedule' )
248
-
253
+ size = 0
254
+ length = self .redis .zcard ('resque:delayed_queue_schedule' )
255
+ for i in self .redis .zrange ('resque:delayed_queue_schedule' ,0 ,length ):
256
+ size += self .delayed_timestamp_size (i )
257
+ return size
258
+
249
259
def delayed_timestamp_size (self , timestamp ):
250
260
#key = int(time.mktime(timestamp.timetuple()))
251
261
return self .redis .llen ("resque:delayed:%s" % timestamp )
252
-
262
+
253
263
def next_delayed_timestamp (self ):
254
264
key = int (time .mktime (ResQ ._current_time ().timetuple ()))
255
- array = self .redis .zrangebyscore ('resque:delayed_queue_schedule' , '-inf' , key )
265
+ array = self .redis .zrangebyscore ('resque:delayed_queue_schedule' ,
266
+ '-inf' , key )
256
267
timestamp = None
257
268
if array :
258
269
timestamp = array [0 ]
259
270
return timestamp
260
-
271
+
261
272
def next_item_for_timestamp (self , timestamp ):
262
273
#key = int(time.mktime(timestamp.timetuple()))
263
274
key = "resque:delayed:%s" % timestamp
@@ -269,7 +280,7 @@ def next_item_for_timestamp(self, timestamp):
269
280
self .redis .delete (key )
270
281
self .redis .zrem ('resque:delayed_queue_schedule' , timestamp )
271
282
return item
272
-
283
+
273
284
@classmethod
274
285
def encode (cls , item ):
275
286
return json .dumps (item )
@@ -280,7 +291,7 @@ def decode(cls, item):
280
291
ret = json .loads (item )
281
292
return ret
282
293
return None
283
-
294
+
284
295
@classmethod
285
296
def _enqueue (cls , klass , * args ):
286
297
queue = getattr (klass ,'queue' , None )
@@ -296,25 +307,25 @@ def _current_time():
296
307
297
308
class Stat (object ):
298
309
"""A Stat class which shows the current status of the queue.
299
-
310
+
300
311
"""
301
312
def __init__ (self , name , resq ):
302
313
self .name = name
303
314
self .key = "resque:stat:%s" % self .name
304
315
self .resq = resq
305
-
316
+
306
317
def get (self ):
307
318
val = self .resq .redis .get (self .key )
308
319
if val :
309
320
return int (val )
310
321
return 0
311
-
322
+
312
323
def incr (self , ammount = 1 ):
313
324
self .resq .redis .incr (self .key , ammount )
314
-
325
+
315
326
def decr (self , ammount = 1 ):
316
327
self .resq .redis .decr (self .key , ammount )
317
-
328
+
318
329
def clear (self ):
319
330
self .resq .redis .delete (self .key )
320
-
331
+
0 commit comments