Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django - Celery: @transaction and @task don't stack

I want to run a Django - Celery task with manual transaction management, but it seems that the annotations do not stack.

e.g.

def ping():
    print 'ping'
    pong.delay('arg')

@task(ignore_result=True)
@transaction.commit_manually()
def pong(arg):
    print 'pong: %s' % arg
    transaction.rollback()

results in

TypeError: pong() got an unexpected keyword argument 'task_name'

while the reverse annotation order results in

---> 22     pong.delay('arg')

AttributeError: 'function' object has no attribute 'delay'

It makes sense, but I'm having trouble finding a nice workaround. The Django docs don't mention alternatives to the annotation, and I don't want to make a class for each celery Task when I don't need one.

Any ideas?

like image 711
Rob Avatar asked Sep 08 '11 15:09

Rob


2 Answers

Previously Celery had some magic where a set of default keyword arguments were passed to the task if it accepted them.

Since version 2.2 you can disable this behaviour, but the easiest is to import the task decorator from celery.task instead of celery.decorators:

from celery.task import task

@task
@transaction.commit_manually
def t():
    pass

The decorators module is deprecated and will be completely removed in 3.0, and the same for the "magic keyword arguments"

Note: For custom Task classes you should set the accept_magic_kwargs attribute to False:

class MyTask(Task):
    accept_magic_kwargs = False

Note2: Make sure your custom decorators preserves the name of the function using functools.wraps, otherwise the task will end up with the wrong name.

like image 112
asksol Avatar answered Sep 28 '22 14:09

asksol


The task decorator generates a class x(Task) from your function with the run method as your target. Suggest you define the class and decorate the method.

Untested e.g.:

class pong(Task):
  ignore_result = True

  @transaction.commit_manually()
  def run(self,arg,**kwargs):
    print 'pong: %s' % arg
    transaction.rollback()
like image 34
MattH Avatar answered Sep 28 '22 14:09

MattH