带有芹菜的 Django - 找不到现有对象

gma*_*map 5 python django asynchronous celery

我在从另一个 celery 任务执行 celery 任务时遇到问题。

这是有问题的片段(数据对象已经存在于数据库中,它的属性只是在 finalize_data 函数中更新):

def finalize_data(data):
    data = update_statistics(data)
    data.save()
    from apps.datas.tasks import optimize_data
    optimize_data.delay(data.pk)

@shared_task
def optimize_data(data_pk):
    data = Data.objects.get(pk=data_pk)
    #Do something with data
Run Code Online (Sandbox Code Playgroud)

调用 optimize_data 函数失败,并显示“数据匹配查询不存在”。

如果我在 finalize_data 函数中调用 pk 函数检索它工作正常。如果我将 celery 任务调用延迟一段时间,它也可以正常工作。

这一行:

optimize_data.apply_async((data.pk,), countdown=10)
Run Code Online (Sandbox Code Playgroud)

代替

optimize_data.delay(data.pk)
Run Code Online (Sandbox Code Playgroud)

工作正常。但我不想在我的代码中使用 hacks。.save() 调用是否有可能异步阻止对该行/对象的访问?

Vig*_*esh 7

我知道这是一个旧帖子,但我今天偶然发现了这个问题。Lee 的回答为我指明了正确的方向,但我认为今天存在更好的解决方案。

使用on_commitDjango 提供的处理程序可以解决这个问题,而无需在代码中采用黑客式的倒计时方式,这对用户来说可能不直观,因为它存在的原因。

我不确定在发布问题时这是否存在,但我只是发布答案,以便将来来到这里的人知道替代方案。

  • 啊哈,刚刚发现这实际上不是问题,“func”仍然会从文档中被调用:“如果您在没有活动事务的情况下调用 on_commit(),则回调将立即执行。” https://docs.djangoproject.com/en/2.2/topics/db/transactions/#django.db.transaction.on_commit (2认同)

Lee*_*Lee 5

我猜你的调用者在芹菜开始处理任务之前没有提交的事务中。因此芹菜找不到记录。这就是为什么添加倒计时使其起作用的原因。

1 秒倒计时可能与示例中的 10 秒倒计时一样有效。我在整个代码中使用了 1 秒倒计时来处理这个问题。

另一种解决方案是停止使用事务。