David Eyk
David Eyk

Reputation: 12521

Rolling back the db transaction for every request in Django

I'm looking at upgrading a Django-based site from v1.4 to v1.9 of the framework. The site performs a critical role in our infrastructure and sees considerable traffic. Our test suite is pretty good, but nowhere near 100% coverage. Because of all this, I'd like to perform the upgrade in a safe and conservative fashion.

I'm inspired by Github's recent approach to rewriting major features by running the new code and old code as experiment and control, returning the result of the old code and logging any differences or errors in the new code.

Because I'm upgrading the framework version itself (along with supporting libraries), I can't just use a Python port of Scientist, like laboratory. It seems to me that the simplest way to do this would be to fork the site itself, send every request to both sites, but only commit and return the result from the control site.

To that end, I would need the experiment site to run against the same database as the control site, but make no commits. It seems to me I should be able to do this by writing some sort of middleware that rolls back the current transaction at the end of the request-response cycle, but I'm not exactly sure how to go about this.

So, my question: how can I roll back every transaction for every request to a Django 1.9 site?

UPDATE:

With a bit more research, it seems like I could get this behavior by enabling ATOMIC_REQUESTS (best setting name ever!) for the database and using custom middleware with a process_response() method that rolls back the transaction. I'd welcome refinements or alternatives.

Upvotes: 0

Views: 476

Answers (2)

Gocht
Gocht

Reputation: 10256

If you want to use @transaction.atomic and still manage the exception, you can use it with with statement:

try:
    with transaction.atomic():
        a.save()
except IntegrityError, e:
    return ....  # Manage the response

Upvotes: 1

Moddasir
Moddasir

Reputation: 1449

you should use annotation @transaction.atomic() like

Transaction rollback

The first option is to roll back the entire transaction. For example::

a.save() # Succeeds, but may be undone by transaction rollback
try:
    b.save() # Could throw exception
except IntegrityError:
    transaction.rollback()
c.save() # Succeeds, but a.save() may have been undone

Calling transaction.rollback() rolls back the entire transaction. Any uncommitted database operations will be lost. In this example, the changes made by a.save() would be lost, even though that operation raised no error itself.

for better understanding just check transaction

Upvotes: 2

Related Questions