from django.db import transaction, connection

class TransactionMiddleware(object):
    def process_job(self, job):
        if not connection.in_atomic_block:
            transaction.set_autocommit(False)

    def process_result(self, job, result, duration):
        if not connection.in_atomic_block:
            transaction.commit()

    def process_exception(self, job, time_taken, *exc_info):
        if not connection.in_atomic_block:
            transaction.rollback()

# Legacy
if not hasattr(connection, 'in_atomic_block'):
    class TransactionMiddleware(object):
        def process_job(self, job):
            transaction.enter_transaction_management()
            transaction.managed(True)

        def process_result(self, job, result, duration):
            if not transaction.is_managed():
                return
            if transaction.is_dirty():
                transaction.commit()
            transaction.leave_transaction_management()

        def process_exception(self, job, time_taken, *exc_info):
            if transaction.is_dirty():
                transaction.rollback()
            transaction.leave_transaction_management()

from django.db import transaction, connection

class TransactionMiddleware(object):
    def process_job(self, job):
        transaction.atomic(savepoint=False).__enter__()

    def process_result(self, job, result, duration):
        transaction.atomic(savepoint=False).__exit__(None, None, None)

    def process_exception(self, job, time_taken, *exc_info):
        transaction.atomic(savepoint=False).__exit__(*exc_info)

# Legacy
if not hasattr(connection, 'in_atomic_block'):
    class TransactionMiddleware(object):
        def process_job(self, job):
            transaction.enter_transaction_management()
            transaction.managed(True)

        def process_result(self, job, result, duration):
            if not transaction.is_managed():
                return
            if transaction.is_dirty():
                transaction.commit()
            transaction.leave_transaction_management()

        def process_exception(self, job, time_taken, *exc_info):
            if transaction.is_dirty():
                transaction.rollback()
            transaction.leave_transaction_management()

Use Django's Atomic decorator logic
Use Django's Atomic decorator logic

We now keep Autocommit on it’s new default of True, as we only need the
ability to rollback the contents of a queue job. By setting
savepoint=False, the whole job will roll back if anything fails, rather
than just up to the containing savepoint.
