Integration with RabbitMQ and Celery
First update taiga-vagrant vm if you're using it, you will have access to the rabbit management console at port 8001 of the host machine. * Defining tasks - Tasks must be defined in a `deferred` module of an app, for example, `taiga.projects.deferred` module. - Tasks must be decorated and given the name "<app>.<task-name>", for example in `taiga.projects.deferred` module: ``` from taiga.celery import app @app.task(name="projects.add") def add(x, y): return x + y ``` - Tasks should be at most just wrappers around service functions to promote re-usability of those functions from other parts of the code, say, management commands and the like. * Calling tasks Tasks should be called using one of the three functions defined in `taiga.deferred` module: - `defer`: Use this function if you need to perform some task asynchronously and GET THE RESULT back later, for example: ``` result = defer("projects.add", x=1, y=2) ... result.get() # => 3 ``` - `call_async`: Use this function when you want to fire off some task. No result is get back. For example: ``` call_async("projects.email_user", user) ``` - `apply_async`: Is the same as `call_async` but since it's a function application and you must pass the args and kwargs together as one parameter each you are allowed to pass celery-specific extra-options (but bear in mind this is not recommended!) ``` apply_async("projects.email_user", args=(user,), kwargs={}, routing_key="tasks.email") ```remotes/origin/enhancement/email-actions
parent
625c705807
commit
0e414267db
|
@ -26,3 +26,5 @@ enum34==1.0
|
||||||
|
|
||||||
django-reversion==1.8.1
|
django-reversion==1.8.1
|
||||||
easy-thumbnails==2.0
|
easy-thumbnails==2.0
|
||||||
|
celery==3.1.12
|
||||||
|
redis==2.10
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
from __future__ import absolute_import, print_function
|
from __future__ import absolute_import, print_function
|
||||||
import os, sys
|
import os, sys
|
||||||
|
|
||||||
|
from .celery import *
|
||||||
|
|
||||||
try:
|
try:
|
||||||
print("Trying import local.py settings...", file=sys.stderr)
|
print("Trying import local.py settings...", file=sys.stderr)
|
||||||
from .local import *
|
from .local import *
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
from kombu import Exchange, Queue
|
||||||
|
|
||||||
|
BROKER_URL = 'amqp://guest:guest@localhost:5672//'
|
||||||
|
CELERY_RESULT_BACKEND = 'redis://localhost:6379/0'
|
||||||
|
|
||||||
|
CELERY_TIMEZONE = 'Europe/Madrid'
|
||||||
|
CELERY_ENABLE_UTC = True
|
||||||
|
|
||||||
|
CELERY_DEFAULT_QUEUE = 'tasks'
|
||||||
|
CELERY_QUEUES = (
|
||||||
|
Queue('tasks', routing_key='task.#'),
|
||||||
|
Queue('transient', routing_key='transient.#', delivery_mode=1)
|
||||||
|
)
|
||||||
|
CELERY_DEFAULT_EXCHANGE = 'tasks'
|
||||||
|
CELERY_DEFAULT_EXCHANGE_TYPE = 'topic'
|
||||||
|
CELERY_DEFAULT_ROUTING_KEY = 'task.default'
|
|
@ -0,0 +1 @@
|
||||||
|
from . import celery
|
|
@ -0,0 +1,12 @@
|
||||||
|
import os
|
||||||
|
|
||||||
|
from celery import Celery
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings')
|
||||||
|
|
||||||
|
app = Celery('taiga')
|
||||||
|
|
||||||
|
app.config_from_object('django.conf:settings')
|
||||||
|
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS, related_name="deferred")
|
|
@ -0,0 +1,43 @@
|
||||||
|
from .celery import app
|
||||||
|
|
||||||
|
|
||||||
|
def defer(task: str, *args, **kwargs):
|
||||||
|
"""Defer the execution of a task.
|
||||||
|
|
||||||
|
Defer the execution of a task and returns a future objects with the following methods among
|
||||||
|
others:
|
||||||
|
- `failed()` Returns `True` if the task failed.
|
||||||
|
- `ready()` Returns `True` if the task has been executed.
|
||||||
|
- `forget()` Forget about the result.
|
||||||
|
- `get()` Wait until the task is ready and return its result.
|
||||||
|
- `result` When the task has been executed the result is in this attribute.
|
||||||
|
More info at Celery docs on `AsyncResult` object.
|
||||||
|
|
||||||
|
:param task: Name of the task to execute.
|
||||||
|
|
||||||
|
:return: A future object.
|
||||||
|
"""
|
||||||
|
return app.send_task(task, args, kwargs, routing_key="transient.deferred")
|
||||||
|
|
||||||
|
|
||||||
|
def call_async(task: str, *args, **kwargs):
|
||||||
|
"""Run a task and ignore its result.
|
||||||
|
|
||||||
|
This is just a star argument version of `apply_async`.
|
||||||
|
|
||||||
|
:param task: Name of the task to execute.
|
||||||
|
:param args: Arguments for the task.
|
||||||
|
:param kwargs: Keyword arguments for the task.
|
||||||
|
"""
|
||||||
|
apply_async(task, args, kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def apply_async(task: str, args=None, kwargs=None, **options):
|
||||||
|
"""Run a task and ignore its result.
|
||||||
|
|
||||||
|
:param task: Name of the task to execute.
|
||||||
|
:param args: Tupple of arguments for the task.
|
||||||
|
:param kwargs: Dict of keyword arguments for the task.
|
||||||
|
:param options: Celery-specific options when running the task. See Celery docs on `apply_async`
|
||||||
|
"""
|
||||||
|
app.send_task(task, args, kwargs, **options)
|
|
@ -0,0 +1,8 @@
|
||||||
|
from celery import Celery
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
|
app = Celery('taiga')
|
||||||
|
|
||||||
|
app.config_from_object('django.conf:settings')
|
||||||
|
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)
|
|
@ -0,0 +1,35 @@
|
||||||
|
from unittest import mock
|
||||||
|
from taiga.deferred import defer, call_async, apply_async
|
||||||
|
|
||||||
|
|
||||||
|
@mock.patch("taiga.deferred.app")
|
||||||
|
def test_defer(app):
|
||||||
|
name = "task name"
|
||||||
|
args = (1, 2)
|
||||||
|
kwargs = {"kw": "keyword argument"}
|
||||||
|
|
||||||
|
defer(name, *args, **kwargs)
|
||||||
|
|
||||||
|
app.send_task.assert_called_once_with(name, args, kwargs, routing_key="transient.deferred")
|
||||||
|
|
||||||
|
|
||||||
|
@mock.patch("taiga.deferred.app")
|
||||||
|
def test_apply_async(app):
|
||||||
|
name = "task name"
|
||||||
|
args = (1, 2)
|
||||||
|
kwargs = {"kw": "keyword argument"}
|
||||||
|
|
||||||
|
apply_async(name, args, kwargs)
|
||||||
|
|
||||||
|
app.send_task.assert_called_once_with(name, args, kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
@mock.patch("taiga.deferred.app")
|
||||||
|
def test_call_async(app):
|
||||||
|
name = "task name"
|
||||||
|
args = (1, 2)
|
||||||
|
kwargs = {"kw": "keyword argument"}
|
||||||
|
|
||||||
|
call_async(name, *args, **kwargs)
|
||||||
|
|
||||||
|
app.send_task.assert_called_once_with(name, args, kwargs)
|
Loading…
Reference in New Issue