PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Sellerie und Transaktion.atomar

Als @dotz erwähnt , ist es kaum sinnvoll, eine asynchrone Aufgabe zu erstellen und sofort zu blockieren und weiter zu warten, bis sie beendet ist.

Wenn Sie es auf diese Weise anhängen (das .get() am Ende), können Sie sicher sein, dass die Datei mymodel Instanzänderungen, die gerade vorgenommen wurden, werden von Ihrem Worker nicht gesehen, da sie noch nicht festgeschrieben werden - denken Sie daran, dass Sie sich immer noch im atomic befinden blockieren.

Stattdessen könnten Sie (ab Django 1.9) die Aufgabe verzögern, bis die aktuelle aktive Transaktion festgeschrieben ist, indem Sie django.db.transaction.on_commit verwenden Haken:

from django.db import transaction

with transaction.atomic():
    mymodel.save()
    transaction.on_commit(lambda:
        mytask.delay(mymodel.id))

Ich verwende dieses Muster ziemlich oft in meinem post_save Signal-Handler, die eine Verarbeitung neuer Modellinstanzen auslösen. Zum Beispiel:

from django.db import transaction
from django.db.models.signals import post_save
from django.dispatch import receiver
from . import models   # Your models defining some Order model
from . import tasks   # Your tasks defining a routine to process new instances

@receiver(post_save, sender=models.Order)
def new_order_callback(sender, instance, created, **kwargs):
    """ Automatically triggers processing of a new Order. """
    if created:
        transaction.on_commit(lambda:
            tasks.process_new_order.delay(instance.pk))

Auf diese Weise wird Ihre Aufgabe jedoch nicht ausgeführt wenn die Datenbanktransaktion fehlschlägt. Dies ist normalerweise das gewünschte Verhalten, aber behalte es im Hinterkopf.

Bearbeiten :Es ist eigentlich schöner, die on_commit celery-Task auf diese Weise zu registrieren (ohne Lambda):

transaction.on_commit(tasks.process_new_order.s(instance.pk).delay)