diff --git a/rq/decorators.py b/rq/decorators.py new file mode 100644 index 0000000..53eb4cb --- /dev/null +++ b/rq/decorators.py @@ -0,0 +1,35 @@ +from .connections import use_connection, get_current_connection +from .queue import Queue + + +class job(object): + + def __init__(self, queue=None): + """ + A decorator that adds a ``delay`` method to the decorated function, + which in turn creates a RQ job when called. Accepts a ``queue`` instance + as an optional argument. For example: + + from rq import Queue, use_connection + use_connection() + q = Queue() + + @job(queue=q) + def simple_add(x, y): + return x + y + + simple_add.delay(1, 2) # Puts simple_add function into queue + + """ + self.queue = queue + + def __call__(self, f): + def delay(*args, **kwargs): + if self.queue is None: + use_connection(get_current_connection()) + self.queue = Queue() + return self.queue.enqueue(f, *args, **kwargs) + f.delay = delay + return f + + diff --git a/tests/fixtures.py b/tests/fixtures.py index 32003de..ada2bf5 100644 --- a/tests/fixtures.py +++ b/tests/fixtures.py @@ -4,6 +4,8 @@ fixtures has a slighty different characteristics. """ import time +from rq.decorators import job + def say_hello(name=None): """A job with a single argument and a return value.""" @@ -48,3 +50,7 @@ class Calculator(object): def calculate(x, y): return x * y / self.denominator + +@job() +def decorated_job(x, y): + return x + y diff --git a/tests/test_decorator.py b/tests/test_decorator.py new file mode 100644 index 0000000..4a6fcb3 --- /dev/null +++ b/tests/test_decorator.py @@ -0,0 +1,29 @@ +from tests import RQTestCase +from tests.fixtures import decorated_job + +from rq.decorators import job +from rq.job import Job + + +class TestDecorator(RQTestCase): + + def setUp(self): + super(TestDecorator, self).setUp() + + def test_decorator_preserves_functionality(self): + """ + Ensure that a decorated function's functionality is still preserved + """ + self.assertEqual(decorated_job(1, 2), 3) + + def test_decorator_adds_delay_attr(self): + """ + Ensure that decorator adds a delay attribute to function that returns + a Job instance when called. + """ + self.assertTrue(hasattr(decorated_job, 'delay')) + result = decorated_job.delay(1, 2) + self.assertTrue(isinstance(result, Job)) + # Ensure that job returns the right result when performed + self.assertEqual(result.perform(), 3) +