django模型不应该作为参数传递给task

发布时间 2023-10-04 12:16:46作者: 蕝戀

Django 模型对象。它们不应该作为任务的参数传递。当任务运行时从数据库重新获取对象几乎总是更好,因为使用旧数据可能会导致竞争条件。

想象一下以下场景,您有一篇文章和一个自动扩展其中一些缩写的任务:

class Article(models.Model):
    title = models.CharField()
    body = models.TextField()


@app.task
def expand_abbreviations(article):
    article.body.replace('MyCorp', 'My Corporation')
    article.save()

首先,作者创建一篇文章并保存它,然后作者单击启动缩写任务的按钮:

article = Article.objects.get(id=102)
expand_abbreviations.delay(article)

现在,队列非常繁忙,因此该任务将在 2 分钟内不会运行。与此同时,另一位作者对文章进行了更改,因此当任务最终运行时,文章的正文将恢复为旧版本,因为该任务的参数中包含旧的正文。

修复竞争条件很简单,只需使用文章 id,然后重新获取任务正文中的文章即可:

@app.task
def expand_abbreviations(article_id):
    article = Article.objects.get(id=article_id)
    article.body.replace('MyCorp', 'My Corporation')
    article.save()
expand_abbreviations.delay(article_id)