在我当前使用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(如果我确实将它用于正确的事情)?如果是这样,我做错了什么/错过会导致错误?如果没有,那么从数据库中清除无效上传的更好方法是什么?
答案 0 :(得分:1)
您始终可以运行其他任务来查找无效数据点并清理数据库。简而言之,您需要一个具有两阶段提交的分布式事务,这是不容易实现的,因为它有自己的问题而且不确定在Python中是否可用。
答案 1 :(得分:0)
您是否考虑过将transaction.atomic
语句移至任务中?甚至进入插入功能本身?其中任何一个都应该有用。