Best django-orm questions in January 2011

How does commit_on_success handle being nested?

5 votes

Hi,

I'm a bit confused about how I should handle transactions in a particular situation.

I've got some code that boils down to this:

from django.db import transaction

@transaction.commit_on_success
def process_post():
    #do stuff with database
    for reply in post_replies:
        process_post_reply(reply)

@transaction.commit_on_success
def process_post_reply(reply):
    #do stuff with database

I want to know what happens if a process_post_reply() fails.

How does commit_on_success handle being nested? Will it understand to commit each process_post_reply() or if one fails the whole process_post() rolls back?

Here's the source code of it: http://code.djangoproject.com/browser/django/tags/releases/1.2.4/django/db/transaction.py#L286

And enter_transaction_management is as simple as putting new transaction handling mode on thread stack.

So, in your case, if process_post_reply() fails (i.e. exception occurs), then transaction is rolled back in its entirety, and then the exception propagates upwards from process_post() as well but there is nothing to rollback.

And no, if one process_post_reply() fails then whole process_post() is not being rolled back - there's no magic there, only COMMIT and ROLLBACK on database level, which means that what's get rolled back is only what has been writted to DB after last commited process_post_reply().

Summarizing, I think that what you need is just a single commit_on_success() around process_post, possibly supported by transaction savepoints - which unfortunately are available only in PostgreSQL backend, even though MySQL 5.x supports them as well.