【问题标题】:Database in celery task is out datedcelery 任务中的数据库已过时
【发布时间】:2020-06-03 12:24:09
【问题描述】:

我有 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函数和其他副作用。

【问题讨论】:

  • 你在BankEntries表中使用uuid作为主键吗?
  • @NafeesAnwar 更新了代码,以表明我确定创建了 bank_entry 并将 pk 替换为 id

标签: python django celery django-celery


【解决方案1】:

最有可能发生的情况是,您的后台任务正试图在 serializer.save() 完全完成之前访问数据库条目。我以前遇到过类似的问题。

您可以做的是在调用 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()

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

【讨论】:

猜你喜欢
  • 2020-04-05
  • 2019-08-24
  • 2012-10-20
  • 1970-01-01
  • 2013-02-18
  • 2018-12-01
  • 1970-01-01
  • 2018-02-11
  • 1970-01-01
相关资源
最近更新 更多