Skip to content

Commit 9de42ec

Browse files
committed
Merge branch 'master' of git://github.com/binarydud/pyres
2 parents 0251005 + 0f4155a commit 9de42ec

File tree

13 files changed

+192
-40
lines changed

13 files changed

+192
-40
lines changed

HISTORY.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
## 0.4.1 (2010-01-06)
2+
3+
* fixed issue with new failure package in distutils sdist
4+
* changed setup.py to remove camel case, because it's ugly
5+
6+
## 0.4.0 (2010-01-06)
7+
8+
* added the basics of failure backend support
9+
110
## 0.3.1 (2009-12-16)
211

312
* minor bug fix in worker.py

pyres/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
__version__ = '0.3.1'
1+
__version__ = '0.4.1'
22

33
from redis import Redis
44
import simplejson
@@ -75,7 +75,7 @@ def peek(self, queue, start=0, count=1):
7575
return self.list_range('resque:queue:%s' % queue, start, count)
7676

7777
def list_range(self, key, start, count):
78-
items = self.redis.lrange(key,start,start+count-1)
78+
items = self.redis.lrange(key, start,start+count-1)
7979
ret_list = []
8080
for i in items:
8181
ret_list.append(ResQ.decode(i))

pyres/failure/__init__.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import datetime
2+
from pyres import ResQ
3+
import sys, traceback
4+
from pyres.failure.redis import RedisBackend
5+
_backend = RedisBackend
6+
def create(*args, **kwargs):
7+
return _backend(*args, **kwargs)
8+
9+
def count(resq):
10+
return _backend.count(resq)
11+
12+
def all(resq, start, count):
13+
return _backend.all(resq, start, count)
14+
15+
def clear(resq):
16+
return _backend.clear(resq)
17+
18+
def requeue(resq, failure_object):
19+
queue = failure_object._queue
20+
payload = failure_object._payload
21+
return resq.push(queue,payload)
22+
Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import datetime
2-
from pyres import ResQ
3-
import sys, traceback
4-
class Failure(object):
1+
import sys
2+
import traceback
3+
4+
class BaseBackend(object):
55
def __init__(self, exp, queue, payload, worker=None):
66
excc, _, tb = sys.exc_info()
77

@@ -11,6 +11,7 @@ def __init__(self, exp, queue, payload, worker=None):
1111
self._queue = queue
1212
self._payload = payload
1313

14+
1415
def _parse_traceback(self, trace):
1516
"""Return the given traceback string formatted for a notification."""
1617
p_traceback = [ "%s:%d:in `%s'" % (filename, lineno, funcname)
@@ -23,21 +24,4 @@ def _parse_traceback(self, trace):
2324
def _parse_message(self, exc):
2425
"""Return a message for a notification from the given exception."""
2526
return '%s: %s' % (exc.__class__.__name__, str(exc))
26-
27-
def save(self, resq):
28-
data = {
29-
'failed_at' : str(datetime.datetime.now()),
30-
'payload' : self._payload,
31-
'error' : self._parse_message(self._exception),
32-
'backtrace' : self._parse_traceback(self._traceback),
33-
'queue' : self._queue,
34-
'worker' : self._worker
35-
}
36-
data = ResQ.encode(data)
37-
resq.redis.push('resque:failed', data)
38-
39-
@classmethod
40-
def count(cls, resq):
41-
return int(resq.redis.llen('resque:failed'))
42-
43-
27+

pyres/failure/redis.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import datetime
2+
from base import BaseBackend
3+
from pyres import ResQ
4+
class RedisBackend(BaseBackend):
5+
def save(self, resq=None):
6+
if not resq:
7+
resq = ResQ()
8+
data = {
9+
'failed_at' : str(datetime.datetime.now()),
10+
'payload' : self._payload,
11+
'error' : self._parse_message(self._exception),
12+
'backtrace' : self._parse_traceback(self._traceback),
13+
'queue' : self._queue
14+
}
15+
if self._worker:
16+
data['worker'] = self._worker
17+
data = ResQ.encode(data)
18+
resq.redis.push('resque:failed', data)
19+
20+
@classmethod
21+
def count(cls, resq):
22+
return int(resq.redis.llen('resque:failed'))
23+
24+
@classmethod
25+
def all(cls, resq, start=0, count=1):
26+
return resq.list_range('resque:failed', start, count)
27+
28+
@classmethod
29+
def clear(cls, resq):
30+
return resq.redis.delete('resque:failed')
31+

pyres/job.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from pyres import ResQ, str_to_class, safe_str_to_class
2-
from pyres.failure import Failure
2+
from pyres import failure
33
class Job(object):
44
def __init__(self, queue, payload, resq, worker=None):
55
self._queue = queue
@@ -18,8 +18,9 @@ def perform(self):
1818

1919
def fail(self, exception):
2020
#Failure.create(exception)
21-
failure = Failure(exception, self._queue, self._payload, self._worker)
22-
failure.save(self.resq)
21+
fail = failure.create(exception, self._queue, self._payload, self._worker)
22+
fail.save(self.resq)
23+
return fail
2324

2425
@classmethod
2526
def reserve(cls, queue, res, worker=None):

resweb/server.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import os
22
from itty import *
33
from pyres import ResQ
4-
from pyres.failure import Failure
4+
from pyres import failure
55
from views import (
66
Overview,
77
Queues,
@@ -36,7 +36,9 @@ def queue(request, queue_id):
3636

3737
@get('/failed/')
3838
def failed(request):
39-
return str(Failed(HOST).render())
39+
start = request.GET.get('start',0)
40+
start = int(start)
41+
return str(Failed(HOST, start).render())
4042

4143
@get('/workers/(?P<worker_id>\w.+)/')
4244
def worker(request, worker_id):
@@ -69,4 +71,5 @@ def my_media(request, filename):
6971
#return Response(output, content_type=content_type(filename))
7072
#return static_file(request, filename=filename, root=my_root)
7173

72-
#run_itty()
74+
if __name__ == "__main__":
75+
run_itty()

resweb/templates/failed.mustache

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,38 @@
11
{{>header}}
2+
<script type="text/javascript">
3+
$(document).ready(function(){
4+
$('.backtrace').click(function() {
5+
$(this).next().toggle();
6+
return false;
7+
});
8+
});
9+
</script>
210
<h1>Failed Jobs</h1>
3-
Pending Failure module completion!
4-
{{>footer}}
11+
<p class='sub'>Showing {{start}} to {{end}} of <b>{{size}}</b> jobs</p>
12+
13+
<ul class='failed'>
14+
{{#failed_jobs}}
15+
<li>
16+
<dl>
17+
<dt>Worker</dt>
18+
<dd>
19+
<a href="{{worker_url}}">{{worker}}</a> on <b class='queue-tag'>{{queue}}</b > at <b>
20+
<span class="time">{{failed_at}}</span></b>
21+
</dd>
22+
<dt>Class</dt>
23+
<dd><code>{{payload_class}}</code></dd>
24+
<dt>Arguments</dt>
25+
<dd><pre>{{payload_args}}</pre></dd>
26+
<dt>Error</dt>
27+
<dd>
28+
<a href="#" class="backtrace">{{error}}</a>
29+
<pre style='display:none'>{{traceback}}</pre>
30+
</dd>
31+
</dl>
32+
<div class='r'>
33+
</div>
34+
</li>
35+
{{/failed_jobs}}
36+
</ul>
37+
38+
{{>footer}}

resweb/templates/header.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<title>Resque.</title>
55
<link href="{{media_folder}}reset.css" media="screen" rel="stylesheet" type="text/css">
66
<link href="{{media_folder}}style.css" media="screen" rel="stylesheet" type="text/css">
7-
7+
<script src="{{media_folder}}jquery-1.3.2.min.js" type="text/javascript"</script>
88
</head>
99
<body>
1010
<div class="header">

resweb/views.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from pyres import ResQ, __version__
44
from pyres.worker import Worker as Wrkr
5+
from pyres import failure
56
import os
67
TEMPLATE_PATH = os.path.join(os.path.dirname(__file__), 'templates')
78
class ResWeb(pystache.View):
@@ -60,8 +61,8 @@ def empty(self):
6061
return not self._queue
6162

6263
def fail_count(self):
63-
from pyres.failure import Failure
64-
return str(Failure.count(self.resq))
64+
#from pyres.failure import Failure
65+
return str(failure.count(self.resq))
6566

6667
def workers(self):
6768
workers = []
@@ -161,8 +162,25 @@ def __init__(self, host, start=0):
161162
self._start = start
162163
super(Failed, self).__init__(host)
163164

165+
def start(self):
166+
return str(self._start)
167+
168+
def end(self):
169+
return str(self._start + 20)
170+
171+
def size(self):
172+
return str(failure.count(self.resq) or 0)
173+
164174
def failed_jobs(self):
165-
return ''
175+
jobs = []
176+
for job in failure.all(self.resq, self._start, self._start + 20):
177+
item = job
178+
item['worker_url'] = '/workers/%s/' % job['worker']
179+
item['payload_args'] = ','.join(job['payload']['args'])
180+
item['payload_class'] = job['payload']['class']
181+
item['traceback'] = '\n'.join(job['backtrace'])
182+
jobs.append(item)
183+
return jobs
166184

167185
class Stats(ResWeb):
168186
def __init__(self, host, key_id):
@@ -354,4 +372,4 @@ def redis_size(key, resq):
354372
item = resq.redis.scard('resque:'+key)
355373
elif key_type == 'string':
356374
item = 1
357-
return str(item)
375+
return str(item)

0 commit comments

Comments
 (0)