gpt4 book ai didi

mysql - 为什么从 Django pre_save 信号触发的 celery 任务永远看不到对象

转载 作者:行者123 更新时间:2023-11-29 01:05:34 25 4
gpt4 key购买 nike

这是来自 here 的后续问题.

Django 1.3.1, celery 2.2.7,python2.6。

我在 fruits/models.py 中有以下内容:

考虑模型:

class Fruit(models.Model):
name = models.CharField(max_length=50)

def __unicode__(self):
return self.name

fruits/tasks.py 中的以下内容:

from django.dispatch import receiver
from django.db.models import signals

from celery.task import periodic_task, task
import fruits.models as m
import time

@task()
def check_fruit(id):
time.sleep(2)
try:
fruit = m.Fruit.objects.get(pk=id)
print "Fruit %s is found!" % fruit.name
except m.Fruit.DoesNotExist:
print "no such fruit"

@receiver(signals.pre_save, sender=m.Fruit, dispatch_uid="on_fruit_save")
def on_custom_feed_save(sender, instance, **kwargs):
check_fruit.apply_async(args=[instance.id])

我启动 celery 守护进程,然后打开 django shell 并输入:

import fruits.tasks;
import fruits.models as m;
m.Fruit(name="plum").save()

问题:我希望任务能找到水果,但它从来没有找到。为什么?

(我从预保存信号启动任务是为了模拟大型系统上发生的问题)。

最佳答案

老问题其实很简单,问题不是race condition或bug等

该示例从头开始创建新对象,并且该对象在 pre_save 信号期间尚未存储在数据库中。所以 'instance.id' 没有设置,对于新创建的对象它是 None。

check_fruit.delay(None)

由 pre_save 信号调用并产生

fruit = m.Fruit.objects.get(pk=None)

数据库中没有主键为空的行。

Celery 任务实际上正在检查这个查询是否有新创建的对象。查询总是按预期抛出异常。

使用post_save 信号并检查新对象信号的created 参数。

使用 post_save 后,可能会出现与事务相关的竞争条件。大多数时候你不会在意,任务重试主要是有效的。但是,如果您关心竞争条件,请查看新的 django 功能,on_commit Hook

关于mysql - 为什么从 Django pre_save 信号触发的 celery 任务永远看不到对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12175343/

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