База данных по сельдерею устарела - PullRequest
0 голосов
/ 19 февраля 2020

У меня Django == 2.2.8 и сельдерей == 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. Я уверен, что установка сельдерея использует ту же базу данных, потому что при следующем вызове async_create_transactions я вижу предыдущий BankEntry, но не текущий.

У меня нет, ловушек, сигналов, postgresql функции и другие побочные эффекты.

1 Ответ

0 голосов
/ 19 февраля 2020

Наиболее вероятно, что ваша фоновая задача пытается получить доступ к записи базы данных до того, как 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()

Возможно, это не самое элегантное решение, но во многих случаях оно работало для меня.

...