芹菜任务中缺少与Django相关的对象(竞赛条件?) [英] Django related objects are missing from celery task (race condition?)
问题描述
奇怪的行为,我不知道该如何解释。我有一个模型,跟踪
,并带有一些相关的点
。我称一个celery任务来执行一些带点的计算,它们似乎在方法本身中完全可以实现,但是在celery任务中不可用。
Strange behavior, that I don't know how to explain. I've got a model, Track
, with some related points
. I call a celery task to performs some calculations with points, and they seem to be perfectly reachable in the method itself, but unavailable in celery task.
@shared_task
def my_task(track):
print 'in the task', track.id, track.points.all().count()
def some_method():
t = Track()
t.save()
t = fill_with_points(t) # creating points, attaching them to a Track
t.save()
print 'before the task', track.id, track.points.all().count()
my_task.delay(t)
打印以下内容:
before the task, 21346, 2971
in the task, 21346, 0
奇怪的事情,当我在 my_task
的第一行或在完全调用 my_task
之前放置time.sleep(10)时,效果很好,就像有一些比赛条件。但是第一行显示的内容清楚地表明,在进行选择查询时, points
在数据库中可用( track.points.all()。count ()
)。
Strange thing though, when I put a time.sleep(10) at the first line of my_task
or before calling my_task
at all, it works out well, like there's some race condition. But the first printed line clearly says that points
are available in the database, when it makes a select query (track.points.all().count()
).
推荐答案
因此,我已经使用 django-transaction-hooks 。替换我的数据库后端看起来仍然有些恐怖,但是 django-celery-transactions
在Django 1.6中似乎已损坏。现在我的设置如下:
So, I've solved it using django-transaction-hooks. It still looks kinda scary to replace my DB backend, but django-celery-transactions
seems to be broken in Django 1.6. Now my setup looks like this:
settings.py:
settings.py:
DATABASES = {
'default': {
'ENGINE': 'transaction_hooks.backends.postgresql_psycopg2',
'NAME': 'foo',
},
}
SOUTH_DATABASE_ADAPTERS = {'default':'south.db.postgresql_psycopg2'} # this is required, or South breaks
models.py:
models.py:
from django.db import connection
@shared_task
def my_task(track):
print 'in the task', track.id, track.points.all().count()
def some_method():
t = Track()
t.save()
t = fill_with_points(t) # creating points, attaching them to a Track
t.save()
print 'before the task', track.id, track.points.all().count()
connection.on_commit(lambda: my_task.delay(t))
结果:
before the task, 21346, 2971
in the task, 21346, 2971
如此常见的用例没有本机celery或Django解决方案仍然令人感到奇怪。
It still seems strange that such a common use case has no native celery or Django solution.
这篇关于芹菜任务中缺少与Django相关的对象(竞赛条件?)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!