python - celery 任务中的数据库已过时
问题描述
我有 Django==2.2.8 和 celery==4.3.0,redis 作为代理。
有非常简单的drf
视图来创建BankEntry
。
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
instance = serializer.save()
bank_entry = BankEntries.objects.get(pk=instance.id)
async_task = async_create_transactions.delay(bank_entry.pk) <--- celery task
@celery_app.task()
def async_create_transactions(entry_id):
bank_entry = BankEntries.objects.filter(pk=entry_id).first()
if bank_entry: <---- HERE SOMETIMES BANK_ENTRY IS NONE, But why, we just created it
return bank_entry.create_entries()
不知道为什么,但async_create_transactions
我可以得到刚刚创建的 BankEntry。我确定 celery 设置使用相同的数据库,因为在下一次async_create_transactions
通话中,我可以看到以前的 BankEntry 但看不到当前的。
我没有,钩子,信号,postgresql 函数和其他副作用。
解决方案
最有可能发生的是您的后台任务正在尝试在serializer.save()
完全完成之前访问数据库条目。我以前遇到过类似的问题。
您可以做的是在调用 your 后添加一个短暂的延迟,async_create_transactions
这将为完成记录保存留出时间。所以你可以做这样的事情:
from time import sleep
@celery_app.task()
def async_create_transactions(entry_id):
sleep(1)
bank_entry = BankEntries.objects.filter(pk=entry_id).first()
if bank_entry:
return bank_entry.create_entries()
这可能不是最优雅的解决方案,但它在很多情况下都对我有用。
推荐阅读
- javascript - 即使单击父 div,也可以使动态生成的复选框单击工作
- clickhouse - 如何在 ClickHouse 中找到降价的产品?
- php - Laravel make:auth 自定义文件夹
- arrays - 如何确定字符串中的字符串是否包含所有数字
- google-apps-script - 在脚本文件末尾添加排序功能
- qt - 如何使用 opencv VideoCapture 从 Firewire(确切地说是 Fire-i 630c)相机读取帧
- php - 如何在类别网址的末尾添加斜杠并在 wordpress 上的帖子末尾删除它?
- sql - 编写查询以确保所有 Cus_Id 的长度应为 6。如果长度不是 6,则附加所需数量的 '0' 作为前缀
- memory - Solr 在更改内存大小时删除已创建的分片
- c# - 每年的时间线视图(DeveExpress 控件)