[英]Django with Celery - existing object not found
我在从另一个 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
调用 optimize_data 函数失败,并显示“数据匹配查询不存在”。
如果我在 finalize_data 函数中调用 pk 函数检索它工作正常。 如果我将 celery 任务调用延迟一段时间,它也可以正常工作。
这一行:
optimize_data.apply_async((data.pk,), countdown=10)
代替
optimize_data.delay(data.pk)
工作正常。 但我不想在我的代码中使用 hacks。 .save() 调用是否有可能异步阻止对该行/对象的访问?
我猜你的调用者在芹菜开始处理任务之前没有提交的事务中。 因此芹菜找不到记录。 这就是为什么添加倒计时使其起作用的原因。
1 秒倒计时可能与示例中的 10 秒倒计时一样有效。 我在整个代码中使用了 1 秒倒计时来处理这个问题。
另一种解决方案是停止使用事务。
您可以使用on_commit
钩子来确保 celery 任务在事务提交之后才触发?
DjangoDocs#performing-actions-after-commit
这是 Django 1.9 中添加的一项功能。
from django.db import transaction
def do_something():
pass # send a mail, invalidate a cache, fire off a Celery task, etc.
transaction.on_commit(do_something)
您还可以将函数包装在 lambda 中:
transaction.on_commit(lambda: some_celery_task.delay('arg1'))
您传入的函数将在调用 on_commit() 的假设数据库写入成功提交后立即调用。
如果在没有活动事务时调用 on_commit(),回调将立即执行。
如果该假设的数据库写入被回滚(通常是在 atomic() 块中引发未处理的异常时),您的函数将被丢弃并且永远不会被调用。
我来补充@Vignesh的良好反应
该问题的示例将通过以下方式解决:
from django.db import transaction
def finalize_data(data):
data = update_statistics(data)
data.save()
from apps.datas.tasks import optimize_data
transaction.on_commit(lambda: optimize_data.delay(data.pk)) <---- Here
还有其他人认为这是正确的答案吗? 还是还有其他更清晰,更优化的回应? 谢谢
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.