Celery + Django - 与数据库相关的任务

时间:2015-10-07 18:31:11

标签: python django celery

在我当前使用Django,Docker-Compose和Celery(以及其他内容)的项目中,从任务调用基本上传文件函数insertIntoDatabase,在views.py中任务是使用delay调用。

在databaseinserter.py中:

def insertIntoDatabase(datapoints, user, description): # datapoints is a list of dictionaries, user and description are just strings
    # convert data and upload to our database

在tasks.py中:

@app.task()
def db_ins_task(datapoints, user, description):
    from databaseinserter import insertIntoDatabase
    insertIntoDatabase(datapoints, user, description)

在views.py中:

with transaction.atomic():
    db_ins_task.delay(datapoints, user, description)

在将Celery引入项目之前,insertIntoDatabase直接在views.py中调用,因此任何无效的数据点列表(即格式不正确)都不会被插入,整个上传将被取消,回滚。但是,现在上传是在异步芹菜任务中,无法正确回滚无效上载。如果上传是一项任务,我怎样才能确保无效上传仍然被取消并完全取消?似乎Django 1.9有一些新东西可能是我需要的东西:transaction.on_commit。然而,目前切换到1.9的主要问题是它似乎不是我们项目中的重要依赖项,Django-Hstore是兼容的。 1.9也是alpha版本,因此即使两者兼容,它目前还不是理想的。有没有办法在Django 1.8中做到这一点?

我也调查了django_transaction_barrier并试图使用它,但没有运气。在tasks.py中,我将任务更改为

@task(base=TransactionBarrierTask)
def db_ins_task(datapoints, user, description):
    from databaseinserter import insertIntoDatabase
    insertIntoDatabase(datapoints, user, description)

在views.py中,我更改了任务执行:

with transaction.atomic():
    db_ins_task.apply_async_with_barrier(args=(data, user, description,))

但是,我的主要问题是,一旦收到任务,Celery会抛出一个关于意外关键字参数的错误:

worker_1   | Traceback (most recent call last):
worker_1   |   File "/usr/local/lib/python2.7/site-packages/celery/app/trace.py", line 240, in trace_task
worker_1   |     R = retval = fun(*args, **kwargs)
worker_1   |   File "/usr/local/lib/python2.7/site-packages/celery/app/trace.py", line 438, in __protected_call__
worker_1   |     return self.run(*args, **kwargs)
worker_1   | TypeError: db_ins_task() got an unexpected keyword argument '__transaction_barrier'

那么,最好的方法是什么?我是否应该继续尝试使用django_transaction_barrier(如果我确实将它用于正确的事情)?如果是这样,我做错了什么/错过会导致错误?如果没有,那么从数据库中清除无效上传的更好方法是什么?

2 个答案:

答案 0 :(得分:1)

芹菜是一个异步的任务跑步者,基本上一旦任务被交给芹菜,它的火和忘记。您不能跨越流程边界进行事务,因为芹菜将作为工作者运行。

您始终可以运行其他任务来查找无效数据点并清理数据库。简而言之,您需要一个具有两阶段提交的分布式事务,这是不容易实现的,因为它有自己的问题而且不确定在Python中是否可用。

答案 1 :(得分:0)

您是否考虑过将transaction.atomic语句移至任务中?甚至进入插入功能本身?其中任何一个都应该有用。