sql >> Base de Datos >  >> RDS >> PostgreSQL

Apio y transacción.atomic

Como @dotz mencionado , no es útil generar una tarea asíncrona e inmediatamente bloquear y seguir esperando hasta que finalice.

Además, si lo adjunta de esta manera (el .get() al final), puede estar seguro de que mymodel Los cambios de instancia recién realizados no serán vistos por su trabajador porque aún no se confirmarán; recuerde que todavía está dentro del atomic bloquear.

Lo que podría hacer en su lugar (desde Django 1.9) es retrasar la tarea hasta que se confirme la transacción activa actual, usando django.db.transaction.on_commit anzuelo:

from django.db import transaction

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

Uso este patrón con bastante frecuencia en mi post_save manejadores de señales que activan algún procesamiento de nuevas instancias del modelo. Por ejemplo:

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))

De esta manera, sin embargo, su tarea no se ejecutará si la transacción de la base de datos falla. Suele ser el comportamiento deseado, pero tenlo en cuenta.

Editar :En realidad, es mejor registrar la tarea de apio on_commit de esta manera (sin lambda):

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