首页 > 解决方案 > 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 函数和其他副作用。

标签: pythondjangocelerydjango-celery

解决方案


最有可能发生的是您的后台任务正在尝试在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()

这可能不是最优雅的解决方案,但它在很多情况下都对我有用。


推荐阅读