Skip to content

Commit 9440091

Browse files
committed
Add the 'Multiple' backend. As in Resque we delegate all queries to
the first backend in the list. To use: from pyres import failure from pyres.failure.base import BaseBackend from pyres.failure.multiple import MultipleBackend from pyres.failure.redis import RedisBackend class CustomBackend(BaseBackend): def save(self, resq): print('Custom backend') failure.backend = MultipleBackend failure.backend.classes = [RedisBackend, CustomBackend]
1 parent 89b05b9 commit 9440091

File tree

3 files changed

+65
-18
lines changed

3 files changed

+65
-18
lines changed

pyres/failure/__init__.py

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,28 @@
1-
import datetime
2-
from pyres import ResQ
3-
import sys, traceback
41
from pyres.failure.redis import RedisBackend
52

6-
_backend = RedisBackend
3+
backend = RedisBackend
74

85
def create(*args, **kwargs):
9-
return _backend(*args, **kwargs)
6+
return backend(*args, **kwargs)
107

118
def count(resq):
12-
return _backend.count(resq)
9+
return backend.count(resq)
1310

1411
def all(resq, start, count):
15-
return _backend.all(resq, start, count)
12+
return backend.all(resq, start, count)
1613

1714
def clear(resq):
18-
return _backend.clear(resq)
15+
return backend.clear(resq)
1916

2017
def requeue(resq, failure_object):
2118
queue = failure_object._queue
2219
payload = failure_object._payload
2320
return resq.push(queue, payload)
24-
21+
2522
def retry(resq, queue, payload):
2623
job = resq.decode(payload)
2724
resq.push(queue, job['payload'])
2825
return delete(resq, payload)
29-
26+
3027
def delete(resq, payload):
31-
return resq.redis.lrem(name = 'resque:failed', num = 1, value = payload)
32-
28+
return resq.redis.lrem(name='resque:failed', num=1, value=payload)

pyres/failure/multiple.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
from base import BaseBackend
2+
from redis import RedisBackend
3+
4+
class MultipleBackend(BaseBackend):
5+
classes = []
6+
7+
def __init__(self, *args):
8+
if not self.classes:
9+
self.classes = [RedisBackend]
10+
11+
self.backends = [klass(*args) for klass in self.classes]
12+
BaseBackend.__init__(self, *args)
13+
14+
@classmethod
15+
def count(cls, resq):
16+
first = MultipleBackend.classes[0]
17+
return first.count(resq)
18+
19+
@classmethod
20+
def all(cls, resq, start=0, count=1):
21+
first = MultipleBackend.classes[0]
22+
return first.all(resq, start, count)
23+
24+
@classmethod
25+
def clear(cls, resq):
26+
first = MultipleBackend.classes[0]
27+
return first.clear(resq)
28+
29+
def save(self, resq=None):
30+
map(lambda x: x.save(resq), self.backends)

tests/test_failure.py

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,35 @@
11
from tests import PyResTests, Basic, TestProcess, ErrorObject
22
from pyres import failure
3+
from pyres.failure.base import BaseBackend
4+
from pyres.failure.multiple import MultipleBackend
5+
from pyres.failure.redis import RedisBackend
36
from pyres.job import Job
7+
48
class FailureTests(PyResTests):
59
def test_count(self):
610
self.resq.enqueue(Basic,"test1")
711
job = Job.reserve('basic',self.resq)
812
job.fail("problem")
913
assert failure.count(self.resq) == 1
1014
assert self.redis.llen('resque:failed') == 1
11-
15+
1216
def test_create(self):
1317
self.resq.enqueue(Basic,"test1")
1418
job = Job.reserve('basic',self.resq)
1519
e = Exception('test')
1620
fail = failure.create(e, 'basic', job._payload)
1721
assert isinstance(fail._payload, dict)
18-
fail.save()
22+
fail.save(self.resq)
1923
assert failure.count(self.resq) == 1
2024
assert self.redis.llen('resque:failed') == 1
21-
25+
2226
def test_all(self):
2327
self.resq.enqueue(Basic,"test1")
2428
job = Job.reserve('basic',self.resq)
2529
e = Exception('problem')
2630
job.fail(e)
2731
assert len(failure.all(self.resq, 0, 20)) == 1
28-
32+
2933
def test_clear(self):
3034
self.resq.enqueue(Basic,"test1")
3135
job = Job.reserve('basic',self.resq)
@@ -34,7 +38,7 @@ def test_clear(self):
3438
assert self.redis.llen('resque:failed') == 1
3539
failure.clear(self.resq)
3640
assert self.redis.llen('resque:failed') == 0
37-
41+
3842
def test_requeue(self):
3943
self.resq.enqueue(Basic,"test1")
4044
job = Job.reserve('basic',self.resq)
@@ -45,4 +49,21 @@ def test_requeue(self):
4549
assert self.resq.size('basic') == 1
4650
job = Job.reserve('basic',self.resq)
4751
assert job._queue == 'basic'
48-
assert job._payload == {'class':'tests.Basic','args':['test1']}
52+
assert job._payload == {'class':'tests.Basic','args':['test1']}
53+
54+
# Test the MultipleBackend, basically just repeat the above tests, ensuring that
55+
# we've delegated to the methods appropriately
56+
57+
class TestBackend(BaseBackend):
58+
def save(self, resq):
59+
resq.redis.set('testbackend:called', 1)
60+
61+
failure.backend = MultipleBackend
62+
failure.backend.classes = [RedisBackend, TestBackend]
63+
64+
class MultipleFailureTests(FailureTests):
65+
def test_create(self):
66+
# Run the parent test
67+
FailureTests.test_create(self)
68+
# But also ensure the other backends were called
69+
assert int(self.redis.get('testbackend:called')) == 1

0 commit comments

Comments
 (0)