Django集成Huey异步任务时无法查询已创建Post记录的问题
问题原因分析
这是数据库事务未提交导致的典型问题:
- Django 中模型的
save()操作默认运行在数据库事务内,post_save信号是在save()方法执行完成后、当前事务提交前触发的。 - 当你在信号里直接调用Huey异步任务时,任务会被立即发送到Redis队列,Huey Worker会马上执行这个任务。但此时触发信号的原事务还没提交到PostgreSQL,数据库里还不存在这条Post记录,所以
Post.objects.get()会抛出DoesNotExist异常。 - 添加
time.sleep(3)后,原事务刚好完成提交,Worker再执行查询时就能找到记录了,但这种延迟方案完全不可靠,因为事务提交时间受数据库负载等因素影响,无法保证每次都刚好3秒完成。
解决方案
最可靠的解决方式是利用Django的transaction.on_commit()方法,确保异步任务在事务提交后才被发送到队列:
修改app/signals.py中的信号处理函数:
from django.db import transaction from django.db.models.signals import post_save from django.dispatch import receiver from .models import Post @receiver(post_save, sender=Post) def post_signal(sender, instance, **kwargs): from app.tasks import create_or_update_related_objects # 将任务调用包裹在on_commit中,事务提交后才执行 transaction.on_commit(lambda: create_or_update_related_objects(instance.pk))
补充说明
transaction.on_commit()会注册一个回调函数,只有当当前所有嵌套事务都提交完成后,才会执行这个回调。- 这种方式从根本上避免了异步任务与数据库事务的时序冲突,比硬编码延迟的方案更稳定、更高效。
内容的提问来源于stack exchange,提问作者Mirza Delic
相关产品推荐
相关产品推荐

