Skip to content

Commit 0b4af76

Browse files
author
Alexey Tsitkin
committed
py3 support, tests, docs
1 parent 25fe656 commit 0b4af76

File tree

4 files changed

+55
-10
lines changed

4 files changed

+55
-10
lines changed

README.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,32 @@ def group_finished(group_id):
135135
pass
136136
```
137137

138+
#### Auto Tasks
139+
140+
This is a helper tool, for the case you wish to define one of your class method as a task, and make it seamless to all callers.
141+
This makes the code much simpler, and allows using classes to invoke your method directly without considering whether it's invoked async or not.
142+
143+
This is how you would define your class:
144+
```python
145+
class MyService:
146+
def __init__(self, p1=default1, ..., pN=defaultN, auto_task_service=None):
147+
self._auto_task_service = auto_task_service or AutoTaskService()
148+
149+
self._auto_task_service.register_task(self.my_task_method)
150+
151+
def my_task_method(self, *args, **kwargs):
152+
...
153+
154+
```
155+
156+
Notice the following:
157+
1. Your class needs to have defaults for all parameter in the c'tor
158+
2. The c'tor must have a parameter named `auto_task_service`
159+
3. The method shouldn't have any return value (as it's invoked async)
160+
161+
In case you want your method to retry certain cases, you need to raise `RetryableTaskException`.
162+
You can provide on optional `delay` time for the retry, set `count_retries=False` in case you don't want to limit retries, or use `max_retries_func` to specify a function which will be invoked when the defined maximum number of retries is exhausted.
163+
138164
#### Settings
139165

140166
The following settings can be used to fine tune django-eb-sqs. Copy them into your Django `settings.py` file.

eb_sqs/auto_tasks/base_service.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def __init__(self):
1717

1818
def register_task(self, method, queue_name=None, max_retries=None):
1919
# type: (Any, str, int) -> None
20-
self._registered_func_names.append(method.func_name)
20+
self._registered_func_names.append(method.__name__)
2121

2222
def is_func_name_registered(self, func_name):
2323
# type: (str) -> bool

eb_sqs/auto_tasks/service.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,6 @@ def _auto_task_wrapper(module_name, class_name, func_name, *args, **kwargs):
4141
except RetryableTaskException as exc:
4242
try:
4343
retry_kwargs = {}
44-
if 'execute_inline' in kwargs:
45-
retry_kwargs['execute_inline'] = kwargs['execute_inline']
4644

4745
if exc.delay is not None:
4846
retry_kwargs['delay'] = exc.delay
@@ -62,9 +60,9 @@ def _auto_task_wrapper(module_name, class_name, func_name, *args, **kwargs):
6260
class AutoTaskService(BaseAutoTaskService):
6361
def register_task(self, method, queue_name=None, max_retries=None):
6462
# type: (Any, str, int) -> None
65-
instance = method.im_self
63+
instance = method.__self__
6664
class_ = instance.__class__
67-
func_name = method.func_name
65+
func_name = method.__name__
6866

6967
def _auto_task_wrapper_invoker(*args, **kwargs):
7068
if queue_name is not None:

eb_sqs/tests/auto_tasks/tests_auto_tasks.py

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,32 @@
11
from unittest import TestCase
22

3-
from mock import Mock
3+
from mock import Mock, call
44

5+
from eb_sqs import settings
6+
from eb_sqs.auto_tasks.exceptions import RetryableTaskException
57
from eb_sqs.auto_tasks.service import AutoTaskService, _auto_task_wrapper
68

79

810
class TestService:
911
_TEST_MOCK = Mock()
12+
_MAX_RETRY_NUM = 5
1013

1114
def __init__(self, auto_task_service=None):
1215
self._auto_task_service = auto_task_service or AutoTaskService()
1316
self._auto_task_service.register_task(self.task_method)
17+
self._auto_task_service.register_task(self.task_retry_method, max_retries=self._MAX_RETRY_NUM)
1418

1519
def task_method(self, *args, **kwargs):
1620
self._TEST_MOCK.task_method(*args, **kwargs)
1721

22+
def task_retry_method(self, *args, **kwargs):
23+
self._TEST_MOCK.task_retry_method(*args, **kwargs)
24+
25+
def max_retry_fun():
26+
self._TEST_MOCK.task_max_retry_method(*args, **kwargs)
27+
28+
raise RetryableTaskException(Exception('Test'), max_retries_func=max_retry_fun)
29+
1830
def non_task_method(self):
1931
self._TEST_MOCK.non_task_method()
2032

@@ -23,13 +35,22 @@ class AutoTasksTest(TestCase):
2335
def setUp(self):
2436
self._test_service = TestService()
2537

38+
self._args = [5, '6']
39+
self._kwargs = {'p1': 'bla', 'p2': 130}
40+
41+
settings.EXECUTE_INLINE = True
42+
2643
def test_task_method(self):
27-
args = [5, '6']
28-
kwargs = {'p1': 'bla', 'p2': 130}
44+
self._test_service.task_method(*self._args, **self._kwargs)
45+
46+
TestService._TEST_MOCK.task_method.assert_called_once_with(*self._args, **self._kwargs)
47+
48+
def test_task_retry_method(self):
49+
self._test_service.task_retry_method(*self._args, **self._kwargs)
2950

30-
self._test_service.task_method(*args, **dict(kwargs, execute_inline=True))
51+
TestService._TEST_MOCK.task_retry_method.assert_has_calls([call(*self._args, **self._kwargs)] * TestService._MAX_RETRY_NUM)
3152

32-
TestService._TEST_MOCK.task_method.assert_called_once_with(*args, **kwargs)
53+
TestService._TEST_MOCK.task_max_retry_method.assert_called_once_with(*self._args, **self._kwargs)
3354

3455
def test_non_task_method(self):
3556
_auto_task_wrapper.delay(

0 commit comments

Comments
 (0)