gpt4 book ai didi

Django post_save as celery 任务奇怪的行为

转载 作者:行者123 更新时间:2023-12-04 12:51:33 28 4
gpt4 key购买 nike

我有以下代码:

@receiver(post_save, sender=SomeModel, dispatch_uid="build")
def handle_creation(sender, instance, created, **kwargs):
if created == True:
build.delay(instance)

@task()
def build(instance):
instance.status = 'Processing'
instance.save()

#some heavy instructions here
#. . . .
#. . . .

instance.status = 'Finished'
instance.save()

我产生了以下错误:

IntegrityError: duplicate key value violates unique constraint DETAIL:  Key (id)=(13) already exists.

但如果我先删除 instance.save() 一切正常。看起来当 celery 处理任务时 sql 指令没有完成。如何解决?

谢谢。

最佳答案

您的代码有两个问题。

第一个是最大的,您正在将对象实例传递给任务——这在 celery 文档中被明确标记为错误的方法,基本上您正在做的是在某种状态下序列化您的对象并将其传递给 celery 进行处理;但与此同时,这个对象可能会改变;作为解决方案,您应该将对象 ID 作为参数传递,以便 celery 任务可以新鲜获取它:

build.delay(instance.pk)

...

@task
def build(my_key):
instance = SomeModel.objects.get(pk=my_key)
instance.status = 'Processing'
instance.save()

第二个问题本质上很微妙,很少引起注意。您的代码的第一部分可以在事务中调用,这意味着可能存在这样一种情况,即您的任务(在 celery 中)将比事务提交更快,然后您的模型将首先保存在 celery 任务中,然后通过事务- 这里有一个问题。

如果您按照上面的建议更改代码,则描述为第二个问题的情况可能不会发生,或者会显示不同的错误。

为避免此类问题,最好从 transaction.oncommit 处理程序(在 1.9 版中引入 Django)调用 celery 任务

还有一个评论,我可以看到你正在改变对象的状态:

instance.status = 'Processing'

最有可能作为信息,但也可能用作锁定机制...QuerySet 有一个非常好的选项 select_for_update 方法,它允许您锁定一个对象在交易期间。当您执行以下操作时,这对 celery 任务特别有用:

instance = SomeModel.objects.select_for_update().get(pk=my_key)

它会停止你的任务等待其他人完成(不要忘记把 @transaction.atomic 放在这个任务上)

如果您将 nowait=True 传递给 select_for_update - 它会立即生成异常,让您能够处理情况。

关于Django post_save as celery 任务奇怪的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36264971/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com