Django Loop Through Objects After Bulk .update()

Этот код запускается по cron. Поэтому я хочу обновить статус объектов немедленно, чтобы эти объекты не были подняты снова, если второй cron запустится до того, как закончится текущий (что в конечном итоге начнет происходить с моим приложением.)

    # Grab all pending emails.
    emails = delivery_que.objects.filter(status='PENDING')
    emails.update(status='SENDING')

    # Loop through the pending emails.
    for email in emails:

Текущий код не работает, так как у меня, похоже, больше нет доступа к объектам после того, как я .update() их.

Вот обходной путь, который я применил:

    # Grab all pending emails.
    emails = delivery_que.objects.filter(status='PENDING')
    emails.update(status='SENDING')
    emails = delivery_que.objects.filter(status='SENDING')

    # Loop through the pending emails.
    for email in emails:

Есть ли другое лучшее решение, которое я упускаю? Я бы предпочел не запрашивать базу данных снова, чтобы повторно выбрать объекты, к которым у меня уже должен быть доступ из первого запроса.

Проблема здесь в том, что вы запускаете перекрывающиеся процессы, и ни один из них не знает, что делает другой в любой момент времени.

Простое решение:

  1. При запуске задания проверьте наличие записи о блокировке. Если таковая существует, завершите работу.
  2. Добавить запись о блокировке (к модели в БД, коснуться файла, что-то еще).
  3. Обработайте задание.
  4. Снять запись блокировки как последнее, что делает задание.

Слегка более сложное решение:

  1. В начале работы обновите все записи из PENDING до уникального значения для данного процесса (например, PROCESSING_<uuid>)
  2. .
  3. Запустите обновление для записей с этим уникальным значением.

Вы также можете сделать это, добавив в модель еще одно поле, например processing_id и проверив, что оно пустое, а также имеет правильный PENDING статус.

Возможно, самое сложное решение:

  • Сделать процесс идемпотентным ...

Под этим я подразумеваю, что не имеет значения, если он выполняется дважды на одной и той же записи. Судя по приведенному вами коду, это действительно так, поскольку все, что вы делаете, это меняете статус на SENDING, но я предполагаю, что есть код, который вы не показываете, и пользователи получают двойные письма.

Если у вас есть код, гарантирующий, что не будет отправлено двойное письмо, это не будет проблемой - объект может быть обработан дважды, но письмо будет отправлено только в первый раз.

В идеальном мире все процессы, подобные этому, в любом случае должны быть идемпотентными, просто чтобы гарантировать, что у вас никогда не будет никаких проблем, если кому-то удастся запустить его, когда он не должен этого делать.

Такая же проблема здесь: how-to-bulk-update-with-django и Документация Django здесь Bulk Update

Вернуться на верх