p1-taskqueue 0.1.12__py3-none-any.whl → 0.1.13__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of p1-taskqueue might be problematic. Click here for more details.
- {p1_taskqueue-0.1.12.dist-info → p1_taskqueue-0.1.13.dist-info}/METADATA +2 -1
- p1_taskqueue-0.1.13.dist-info/RECORD +10 -0
- taskqueue/celery_app.py +15 -1
- taskqueue/cmanager.py +139 -46
- taskqueue/slack_notifier.py +51 -0
- p1_taskqueue-0.1.12.dist-info/RECORD +0 -9
- {p1_taskqueue-0.1.12.dist-info → p1_taskqueue-0.1.13.dist-info}/WHEEL +0 -0
- {p1_taskqueue-0.1.12.dist-info → p1_taskqueue-0.1.13.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: p1-taskqueue
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.13
|
|
4
4
|
Summary: A Task Queue Wrapper for Dekoruma Backend
|
|
5
5
|
Author-email: Chalvin <engineering@dekoruma.com>
|
|
6
6
|
Project-URL: Homepage, https://github.com/Dekoruma/p1-taskqueue
|
|
@@ -19,6 +19,7 @@ Requires-Dist: kombu>=5.5.4
|
|
|
19
19
|
Requires-Dist: django>=4.0.0
|
|
20
20
|
Requires-Dist: django-celery-results>=2.6.0
|
|
21
21
|
Requires-Dist: django-celery-beat>=2.8.1
|
|
22
|
+
Requires-Dist: requests>=2.32.3
|
|
22
23
|
Provides-Extra: dev
|
|
23
24
|
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
24
25
|
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
taskqueue/__init__.py,sha256=nNHXIyysNLom9f8of-d__pWJ-YF53Mbrbsb1frPzPPI,298
|
|
2
|
+
taskqueue/celery_app.py,sha256=rLIYRBBgYaQiXEqz-zCntvS8xU4eFZ9YuhJBfIye9E0,3931
|
|
3
|
+
taskqueue/cmanager.py,sha256=9jxcTsWOpzexV3SkRhlY-PkhrobEdMuQVm6tWVVzgTs,16260
|
|
4
|
+
taskqueue/slack_notifier.py,sha256=ZvTbWa1XXHUiciYF14_SH5af0BvGoPCBQohPtxx4FgU,1419
|
|
5
|
+
taskqueue/libs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
+
taskqueue/libs/helper_test.py,sha256=JCdh2S29PpL8RqUxqkcIqwIvr3M9puqHglBZAmfPkuw,7722
|
|
7
|
+
p1_taskqueue-0.1.13.dist-info/METADATA,sha256=pr73Jir2XbTBsq2HieYSEO4h0a_FM5KV15THqfedOM0,1597
|
|
8
|
+
p1_taskqueue-0.1.13.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
9
|
+
p1_taskqueue-0.1.13.dist-info/top_level.txt,sha256=hA3SM1ik2K8iPqtlt_-_nJ4TAePwHPN3vsOc4EiynqU,10
|
|
10
|
+
p1_taskqueue-0.1.13.dist-info/RECORD,,
|
taskqueue/celery_app.py
CHANGED
|
@@ -2,10 +2,14 @@
|
|
|
2
2
|
Celery application setup for TaskQueue.
|
|
3
3
|
Reads configuration from Django settings and auto-configures queues with DLQ.
|
|
4
4
|
"""
|
|
5
|
+
import logging
|
|
6
|
+
|
|
5
7
|
from celery import Celery
|
|
6
8
|
from kombu import Exchange
|
|
7
9
|
from kombu import Queue
|
|
8
10
|
|
|
11
|
+
logger = logging.getLogger(__name__)
|
|
12
|
+
|
|
9
13
|
|
|
10
14
|
def get_django_settings():
|
|
11
15
|
"""Get Django settings, fail fast if not properly configured."""
|
|
@@ -63,7 +67,6 @@ def setup_queues(app, settings, celery_config):
|
|
|
63
67
|
queue_names = ['default', 'high', 'low']
|
|
64
68
|
dlq_name_prefix = getattr(settings, 'TASKQUEUE_DLQ_NAME_PREFIX', 'dlq')
|
|
65
69
|
|
|
66
|
-
# Create exchanges
|
|
67
70
|
main_exchange = Exchange(app_name, type='direct')
|
|
68
71
|
dlx_exchange = Exchange(f'{app_name}.dlx', type='direct')
|
|
69
72
|
|
|
@@ -95,5 +98,16 @@ def setup_queues(app, settings, celery_config):
|
|
|
95
98
|
'task_queues': tuple(queues),
|
|
96
99
|
})
|
|
97
100
|
|
|
101
|
+
try:
|
|
102
|
+
with app.connection_or_acquire() as conn:
|
|
103
|
+
main_exchange.declare(channel=conn.default_channel)
|
|
104
|
+
dlx_exchange.declare(channel=conn.default_channel)
|
|
105
|
+
|
|
106
|
+
for queue in queues:
|
|
107
|
+
queue.declare(channel=conn.default_channel)
|
|
108
|
+
except Exception as e:
|
|
109
|
+
logger.warning(
|
|
110
|
+
f"[TaskQueue] Failed to declare queues: {str(e.__class__.__name__)} {e}")
|
|
111
|
+
|
|
98
112
|
|
|
99
113
|
celery_app = create_celery_app()
|
taskqueue/cmanager.py
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import importlib
|
|
2
2
|
import inspect
|
|
3
3
|
import logging
|
|
4
|
-
from datetime import datetime
|
|
5
|
-
from datetime import timedelta
|
|
6
4
|
from typing import Any
|
|
7
5
|
from typing import Dict
|
|
8
6
|
from typing import Tuple
|
|
9
7
|
|
|
10
8
|
from celery import shared_task
|
|
9
|
+
from celery.exceptions import Reject
|
|
10
|
+
from taskqueue.slack_notifier import SlackbotManager
|
|
11
11
|
|
|
12
12
|
# Setup logger
|
|
13
13
|
logger = logging.getLogger(__name__)
|
|
@@ -50,7 +50,8 @@ def _extract_init_args_from_instance(instance: Any) -> Tuple[list, dict]:
|
|
|
50
50
|
def _split_function_and_queue_kwargs(kwargs: Dict[str, Any]) -> Tuple[Dict[str, Any], Dict[str, Any]]:
|
|
51
51
|
# To prevent confusion whether a kwargs is for function or queue kwargs(i.e celery options and on_commit),
|
|
52
52
|
# ignore confusing kwargs while give warning
|
|
53
|
-
supported_queue_keys = {"channel", "retry",
|
|
53
|
+
supported_queue_keys = {"channel", "retry",
|
|
54
|
+
"on_commit", "job_timeout", "use_legacy_executor"}
|
|
54
55
|
ignored_non_function_keys = {
|
|
55
56
|
"queue", "countdown", "eta", "expires", "priority", "task_id", "routing_key",
|
|
56
57
|
"serializer", "compression", "headers", "link", "link_error", "retry_policy",
|
|
@@ -74,6 +75,17 @@ def _split_function_and_queue_kwargs(kwargs: Dict[str, Any]) -> Tuple[Dict[str,
|
|
|
74
75
|
return func_kwargs, queue_kwargs
|
|
75
76
|
|
|
76
77
|
|
|
78
|
+
def _build_callable_task_call(func: Any, func_args: tuple, func_kwargs: dict) -> Tuple[str, list, dict]:
|
|
79
|
+
task_name = "taskqueue.cmanager.callable_executor"
|
|
80
|
+
task_args = []
|
|
81
|
+
task_kwargs = {
|
|
82
|
+
"callable_obj": func,
|
|
83
|
+
"args": list(func_args),
|
|
84
|
+
"kwargs": dict(func_kwargs),
|
|
85
|
+
}
|
|
86
|
+
return task_name, task_args, task_kwargs
|
|
87
|
+
|
|
88
|
+
|
|
77
89
|
def _build_dynamic_task_call(func: Any, *args: Any, **func_kwargs: Any) -> Tuple[str, list, dict]:
|
|
78
90
|
if _is_class_method(func):
|
|
79
91
|
instance = getattr(func, "__self__")
|
|
@@ -155,47 +167,21 @@ class CManager:
|
|
|
155
167
|
'enqueue_op_type', K_ENQUEUE_OP_TYPE_ENQUEUE)
|
|
156
168
|
|
|
157
169
|
try:
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
raise ValueError(
|
|
161
|
-
"enqueue requires a callable as the first positional argument")
|
|
162
|
-
func = args[0]
|
|
163
|
-
func_args = args[1:]
|
|
164
|
-
|
|
165
|
-
elif enqueue_op_type == K_ENQUEUE_OP_TYPE_ENQUEUE_AT:
|
|
166
|
-
if len(args) < 2:
|
|
167
|
-
raise ValueError(
|
|
168
|
-
"enqueue_at requires (eta_datetime, func, *func_args)")
|
|
169
|
-
eta: datetime = args[0]
|
|
170
|
-
func = args[1]
|
|
171
|
-
func_args = args[2:]
|
|
172
|
-
|
|
173
|
-
elif enqueue_op_type == K_ENQUEUE_OP_TYPE_ENQUEUE_IN:
|
|
174
|
-
if len(args) < 2:
|
|
175
|
-
raise ValueError(
|
|
176
|
-
"enqueue_in requires (countdown_delta, func, *func_args)")
|
|
177
|
-
delta: timedelta = args[0]
|
|
178
|
-
func = args[1]
|
|
179
|
-
func_args = args[2:]
|
|
180
|
-
else:
|
|
181
|
-
raise ValueError(
|
|
182
|
-
f"Unknown enqueue operation type: {enqueue_op_type}")
|
|
183
|
-
|
|
184
|
-
func_kwargs, queue_kwargs = _split_function_and_queue_kwargs(
|
|
185
|
-
kwargs)
|
|
170
|
+
func, func_args, func_kwargs, queue_options = self._parse_enqueue_args(
|
|
171
|
+
enqueue_op_type, args, kwargs)
|
|
186
172
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
queue_kwargs["eta"] = eta
|
|
190
|
-
elif enqueue_op_type == K_ENQUEUE_OP_TYPE_ENQUEUE_IN:
|
|
191
|
-
queue_kwargs = dict(queue_kwargs)
|
|
192
|
-
queue_kwargs["countdown"] = int(delta.total_seconds())
|
|
173
|
+
use_legacy_executor = queue_options.pop(
|
|
174
|
+
'use_legacy_executor', True)
|
|
193
175
|
|
|
194
|
-
|
|
195
|
-
|
|
176
|
+
if use_legacy_executor:
|
|
177
|
+
task_name, task_args, task_kwargs = _build_dynamic_task_call(
|
|
178
|
+
func, *func_args, **func_kwargs)
|
|
179
|
+
else:
|
|
180
|
+
task_name, task_args, task_kwargs = _build_callable_task_call(
|
|
181
|
+
func, func_args, func_kwargs)
|
|
196
182
|
|
|
197
183
|
task_id = self._send_task(task_name, task_args,
|
|
198
|
-
task_kwargs,
|
|
184
|
+
task_kwargs, queue_options)
|
|
199
185
|
|
|
200
186
|
logger.info('[_enqueue_op_base %s] Submit Celery Task SUCCESS, task_name: %s args: %s, kwargs: %s, task_id: %s' % (
|
|
201
187
|
enqueue_op_type, task_name, task_args, task_kwargs, task_id))
|
|
@@ -205,6 +191,46 @@ class CManager:
|
|
|
205
191
|
enqueue_op_type, str(e), args, kwargs))
|
|
206
192
|
raise e
|
|
207
193
|
|
|
194
|
+
def _parse_enqueue_args(self, enqueue_op_type: str, args: tuple, kwargs: dict) -> Tuple[Any, tuple, dict, dict]:
|
|
195
|
+
"""Parse enqueue arguments and return func, func_args, func_kwargs, and queue_options."""
|
|
196
|
+
if enqueue_op_type == K_ENQUEUE_OP_TYPE_ENQUEUE:
|
|
197
|
+
if not args:
|
|
198
|
+
raise ValueError(
|
|
199
|
+
"enqueue requires a callable as the first positional argument")
|
|
200
|
+
func = args[0]
|
|
201
|
+
func_args = args[1:]
|
|
202
|
+
eta, delta = None, None
|
|
203
|
+
|
|
204
|
+
elif enqueue_op_type == K_ENQUEUE_OP_TYPE_ENQUEUE_AT:
|
|
205
|
+
if len(args) < 2:
|
|
206
|
+
raise ValueError(
|
|
207
|
+
"enqueue_at requires (eta_datetime, func, *func_args)")
|
|
208
|
+
eta = args[0]
|
|
209
|
+
func = args[1]
|
|
210
|
+
func_args = args[2:]
|
|
211
|
+
delta = None
|
|
212
|
+
|
|
213
|
+
elif enqueue_op_type == K_ENQUEUE_OP_TYPE_ENQUEUE_IN:
|
|
214
|
+
if len(args) < 2:
|
|
215
|
+
raise ValueError(
|
|
216
|
+
"enqueue_in requires (countdown_delta, func, *func_args)")
|
|
217
|
+
delta = args[0]
|
|
218
|
+
func = args[1]
|
|
219
|
+
func_args = args[2:]
|
|
220
|
+
eta = None
|
|
221
|
+
else:
|
|
222
|
+
raise ValueError(
|
|
223
|
+
f"Unknown enqueue operation type: {enqueue_op_type}")
|
|
224
|
+
|
|
225
|
+
func_kwargs, queue_options = _split_function_and_queue_kwargs(kwargs)
|
|
226
|
+
|
|
227
|
+
if eta is not None:
|
|
228
|
+
queue_options["eta"] = eta
|
|
229
|
+
elif delta is not None:
|
|
230
|
+
queue_options["countdown"] = int(delta.total_seconds())
|
|
231
|
+
|
|
232
|
+
return func, func_args, func_kwargs, queue_options
|
|
233
|
+
|
|
208
234
|
def _send_task(self, task_name: str, task_args: list, task_kwargs: dict, queue_kwargs: Dict[str, Any]) -> str:
|
|
209
235
|
celery_app = self._get_celery_app()
|
|
210
236
|
|
|
@@ -237,7 +263,54 @@ class CManager:
|
|
|
237
263
|
cm = CManager()
|
|
238
264
|
|
|
239
265
|
|
|
240
|
-
@shared_task(bind=True, max_retries=K_MAX_RETRY_COUNT)
|
|
266
|
+
@shared_task(bind=True, max_retries=K_MAX_RETRY_COUNT, acks_late=True, reject_on_worker_lost=True)
|
|
267
|
+
def callable_executor(self, callable_obj=None, args=None, kwargs=None, retry=None):
|
|
268
|
+
job_id = self.request.id
|
|
269
|
+
try:
|
|
270
|
+
args = args or []
|
|
271
|
+
kwargs = kwargs or {}
|
|
272
|
+
callable_name = getattr(callable_obj, '__name__', str(callable_obj))
|
|
273
|
+
|
|
274
|
+
logger.info(
|
|
275
|
+
f"[TaskQueue] Executing callable: {callable_name} with args: {args} and kwargs: {kwargs}, job_id: {job_id}")
|
|
276
|
+
|
|
277
|
+
callable_obj(*args, **kwargs)
|
|
278
|
+
|
|
279
|
+
logger.info(
|
|
280
|
+
f"[TaskQueue] Callable execution completed successfully, callable: {callable_name}, args: {args}, kwargs: {kwargs}, job_id: {job_id}")
|
|
281
|
+
return None
|
|
282
|
+
except Exception as e:
|
|
283
|
+
logger.exception(
|
|
284
|
+
f"[TaskQueue] Error executing callable: {callable_name}, args: {args}, kwargs: {kwargs}, error_class: {e.__class__.__name__}, error: {e}, job_id: {job_id}")
|
|
285
|
+
|
|
286
|
+
current_retries = getattr(self.request, 'retries', 0) or 0
|
|
287
|
+
max_retries = self.max_retries or K_MAX_RETRY_COUNT
|
|
288
|
+
if isinstance(retry, dict) and 'max_retries' in retry:
|
|
289
|
+
max_retries = retry['max_retries']
|
|
290
|
+
|
|
291
|
+
if current_retries >= max_retries:
|
|
292
|
+
logger.error(
|
|
293
|
+
f"[TaskQueue] Max retries ({max_retries}) reached for callable: {callable_name}, job_id: {job_id}")
|
|
294
|
+
self.update_state(state='FAILURE', meta={
|
|
295
|
+
'exc_type': type(e).__name__, 'exc_message': str(e)})
|
|
296
|
+
|
|
297
|
+
SlackbotManager.send_message(
|
|
298
|
+
f"Job Failed Too Many Times - Moving back to dlq.\n"
|
|
299
|
+
f"function name: {callable_name}\n"
|
|
300
|
+
f"args: {args}\n"
|
|
301
|
+
f"kwargs: {kwargs}"
|
|
302
|
+
)
|
|
303
|
+
|
|
304
|
+
raise Reject(reason=str(e), requeue=False)
|
|
305
|
+
|
|
306
|
+
countdown = K_DEFAULT_RETRY_COUNTDOWN
|
|
307
|
+
if isinstance(retry, dict) and 'countdown' in retry:
|
|
308
|
+
countdown = retry['countdown']
|
|
309
|
+
|
|
310
|
+
raise self.retry(exc=e, countdown=countdown, max_retries=max_retries)
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
@shared_task(bind=True, max_retries=K_MAX_RETRY_COUNT, acks_late=True, reject_on_worker_lost=True)
|
|
241
314
|
def dynamic_function_executor(self, module_path=None, function_name=None, args=None, kwargs=None, retry=None):
|
|
242
315
|
job_id = self.request.id
|
|
243
316
|
try:
|
|
@@ -261,8 +334,18 @@ def dynamic_function_executor(self, module_path=None, function_name=None, args=N
|
|
|
261
334
|
|
|
262
335
|
if current_retries >= max_retries:
|
|
263
336
|
logger.error(
|
|
264
|
-
f"[TaskQueue] Max retries ({max_retries}) reached for function: {function_name},
|
|
265
|
-
|
|
337
|
+
f"[TaskQueue] Max retries ({max_retries}) reached for function: {function_name}, job_id: {job_id}")
|
|
338
|
+
self.update_state(state='FAILURE', meta={
|
|
339
|
+
'exc_type': type(e).__name__, 'exc_message': str(e)})
|
|
340
|
+
|
|
341
|
+
SlackbotManager.send_message(
|
|
342
|
+
f"Job Failed Too Many Times - Moving back to dlq.\n"
|
|
343
|
+
f"function name: {function_name}\n"
|
|
344
|
+
f"args: {args}\n"
|
|
345
|
+
f"kwargs: {kwargs}"
|
|
346
|
+
)
|
|
347
|
+
|
|
348
|
+
raise Reject(reason=str(e), requeue=False)
|
|
266
349
|
|
|
267
350
|
countdown = K_DEFAULT_RETRY_COUNTDOWN
|
|
268
351
|
if isinstance(retry, dict) and 'countdown' in retry:
|
|
@@ -271,7 +354,7 @@ def dynamic_function_executor(self, module_path=None, function_name=None, args=N
|
|
|
271
354
|
raise self.retry(exc=e, countdown=countdown, max_retries=max_retries)
|
|
272
355
|
|
|
273
356
|
|
|
274
|
-
@shared_task(bind=True, max_retries=K_MAX_RETRY_COUNT)
|
|
357
|
+
@shared_task(bind=True, max_retries=K_MAX_RETRY_COUNT, acks_late=True, reject_on_worker_lost=True)
|
|
275
358
|
def dynamic_class_method_executor(self, module_path=None, class_name=None, method_name=None, args=None, kwargs=None, init_args=None, init_kwargs=None, retry=None):
|
|
276
359
|
job_id = self.request.id
|
|
277
360
|
try:
|
|
@@ -299,8 +382,18 @@ def dynamic_class_method_executor(self, module_path=None, class_name=None, metho
|
|
|
299
382
|
|
|
300
383
|
if current_retries >= max_retries:
|
|
301
384
|
logger.error(
|
|
302
|
-
f"[TaskQueue] Max retries ({max_retries}) reached for method: {method_name},
|
|
303
|
-
|
|
385
|
+
f"[TaskQueue] Max retries ({max_retries}) reached for method: {method_name}, job_id: {job_id}")
|
|
386
|
+
self.update_state(state='FAILURE', meta={
|
|
387
|
+
'exc_type': type(e).__name__, 'exc_message': str(e)})
|
|
388
|
+
|
|
389
|
+
SlackbotManager.send_message(
|
|
390
|
+
f"Job Failed Too Many Times - Moving back to dlq.\n"
|
|
391
|
+
f"function name: {class_name}.{method_name}\n"
|
|
392
|
+
f"args: {args}\n"
|
|
393
|
+
f"kwargs: {kwargs}"
|
|
394
|
+
)
|
|
395
|
+
|
|
396
|
+
raise Reject(reason=str(e), requeue=False)
|
|
304
397
|
|
|
305
398
|
countdown = K_DEFAULT_RETRY_COUNTDOWN
|
|
306
399
|
if isinstance(retry, dict) and 'countdown' in retry:
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Slack notification for TaskQueue.
|
|
3
|
+
"""
|
|
4
|
+
import json
|
|
5
|
+
import logging
|
|
6
|
+
|
|
7
|
+
import requests
|
|
8
|
+
|
|
9
|
+
logger = logging.getLogger(__name__)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class SlackbotManager:
|
|
13
|
+
|
|
14
|
+
@classmethod
|
|
15
|
+
def send_message(cls, message: str) -> None:
|
|
16
|
+
try:
|
|
17
|
+
from django.conf import settings
|
|
18
|
+
except ImportError:
|
|
19
|
+
return
|
|
20
|
+
|
|
21
|
+
if not getattr(settings, 'TASKQUEUE_SLACK_ENABLED', False):
|
|
22
|
+
return
|
|
23
|
+
|
|
24
|
+
hook_url = getattr(settings, 'TASKQUEUE_SLACK_HOOK_URL', None)
|
|
25
|
+
if not hook_url:
|
|
26
|
+
return
|
|
27
|
+
|
|
28
|
+
channel = getattr(
|
|
29
|
+
settings, 'TASKQUEUE_SLACK_CHANNEL_NAME', '#tech-automation')
|
|
30
|
+
username = getattr(
|
|
31
|
+
settings, 'TASKQUEUE_SLACK_USERNAME', 'TaskQueueBot')
|
|
32
|
+
icon_emoji = getattr(
|
|
33
|
+
settings, 'TASKQUEUE_SLACK_ICON_EMOJI', ':robot_face:')
|
|
34
|
+
|
|
35
|
+
is_staging = getattr(settings, 'IS_RUN_IN_STAGING_ENV', False)
|
|
36
|
+
if is_staging:
|
|
37
|
+
message = '[STAGING] ' + message
|
|
38
|
+
|
|
39
|
+
try:
|
|
40
|
+
requests.post(
|
|
41
|
+
hook_url,
|
|
42
|
+
data=json.dumps({
|
|
43
|
+
'channel': channel,
|
|
44
|
+
'username': username,
|
|
45
|
+
'text': message,
|
|
46
|
+
'icon_emoji': icon_emoji,
|
|
47
|
+
}),
|
|
48
|
+
headers={"Content-Type": "application/json"}
|
|
49
|
+
)
|
|
50
|
+
except Exception as e:
|
|
51
|
+
logger.exception('[TaskQueue Slack] Error: %s', str(e))
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
taskqueue/__init__.py,sha256=nNHXIyysNLom9f8of-d__pWJ-YF53Mbrbsb1frPzPPI,298
|
|
2
|
-
taskqueue/celery_app.py,sha256=neNjLNDouBwUJsDHn6q3cgQQnmwjBFJ0xTVWHR8cWvY,3482
|
|
3
|
-
taskqueue/cmanager.py,sha256=dzYubR9SkMzEYuatt3AL_umkVX_l5BHenz3urp14mLw,12411
|
|
4
|
-
taskqueue/libs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
|
-
taskqueue/libs/helper_test.py,sha256=JCdh2S29PpL8RqUxqkcIqwIvr3M9puqHglBZAmfPkuw,7722
|
|
6
|
-
p1_taskqueue-0.1.12.dist-info/METADATA,sha256=9NOpVhO1MhpRLe7B96FfLZmgLE8Sn8AIEpXeDsoISHU,1565
|
|
7
|
-
p1_taskqueue-0.1.12.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
8
|
-
p1_taskqueue-0.1.12.dist-info/top_level.txt,sha256=hA3SM1ik2K8iPqtlt_-_nJ4TAePwHPN3vsOc4EiynqU,10
|
|
9
|
-
p1_taskqueue-0.1.12.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|