在 Django Admin 中保存新对象并发送到 Celery 任务后,匹配查询不存在
Posted
技术标签:
【中文标题】在 Django Admin 中保存新对象并发送到 Celery 任务后,匹配查询不存在【英文标题】:Matching query doesn't exist after a new object save in Django Admin and sent to Celery task 【发布时间】:2015-09-07 03:47:28 【问题描述】:我在 Django Admin (Django 1.8) 中保存一个对象并将它们传递给 Celery Task。不幸的是,我得到了一个错误[有时!]:“匹配的查询不存在”。我知道这是事务的问题,但解决该问题的最佳方法是什么?
class MyModelAdmin(admin.ModelAdmin)
def save_model(self, request, obj, form, change):
super(MyAdmin, self).save_model(request, obj, form, change)
if not change:
celery_task.delay(obj.pk)
@app.task()
def celery_task(obj_pk):
MyModel.objects.get(pk=obj_pk)
问题是 Django Admin 中的整个视图位于 transaction.atomic() 块中。有时 celery 运行速度比交易结束时更快。我想知道解决这个问题的最佳方法是什么。我认为在调用 celery_task 时添加 eta 是一个令人毛骨悚然的想法(或者可能不是?) - celery_task.apply_async((obj.pk,), eta=+10 seconds)
【问题讨论】:
在这方面也许有一些有趣的链接:集成post commit hooks 的票被接受(并且还有一个指向 contrib 包的链接)。在此之前,我认为eta
以及配置重试间隔似乎并不是一个令人毛骨悚然的想法(但对其他观点感到好奇)。至少它保持简单的方式。否则,您还可以运行一些独立的作业,每隔 X 间隔检查数据库是否有新更改,并从那里触发任务。
为什么不尝试在post_save
信号上调用 celery 任务?
@argaen post_save
在事务块中也被调用。
【参考方案1】:
我认为eta
是个好主意。但是竞态条件的可能性仍然存在,因此您可以使用eta
retry a task 进行故障转移:
@app.task(default_retry_delay=60, max_retries=3) # retry in 1 minute with maximum 3 retries
def celery_task(obj_pk):
try:
MyModel.objects.get(pk=obj_pk)
except MyModel.DoesNotExist, exc:
celery_task.retry(exc=exc)
【讨论】:
以上是关于在 Django Admin 中保存新对象并发送到 Celery 任务后,匹配查询不存在的主要内容,如果未能解决你的问题,请参考以下文章
防止 Django 在并发请求时将同一个对象多次保存到数据库中
Django-Admin TabularInline 在保存前修改内联项属性