Reputation: 57198
I'm no transaction / database expert, so pardon my ignorance in the wording here:
When you use Django's transaction.commit_on_success(func)
, any error that's propagated to the control of commit_on_success
will roll back the transaction which is really helpful of course in case you need some all-or-nothing action in a method, etc. This makes Django's view-based transaction handling great for views that do a lot of stuff.
Sometimes I wrap model methods or plain old helper functions in commit_on_success
to achieve the same all-or-nothing behavior.
The problem comes when you have nested Django transactions. Example: A transaction protected view calls a model method that's wrapped in commit_on_success
and then does some other stuff with another model and causes an exception. Oops, when control returned to commit_on_success
from the model method the transaction was committed and now the view errors out changing my view to all-or-some instead of all-or-nothing. This isn't limited to views. I may have nested operations going on which all lots_o_foo_or_nothing()
uses commit_on_success
and calls all_or_nothing_1()
and all_or_nothing_2()
which are both wrapped in commit_on_success
. If lots_o_foo_or_nothing()
errors out the sub function calls will have already committed their transactions to the DB, logically corrupting my data.
Is there a way around this? Again, pardon me, if I'm misunderstanding something, but it seems this is the behavior I've witnessed, and a way around it would be a great convenience.
Upvotes: 3
Views: 912
Reputation: 3752
not a final solution but an idea based on this snippet (which is good idea per se)
this plus savepoints can create nice solution: a decorator, which will be aware if transaction is inside other transaction (and if it is, is using savepoints instead of transactions).
Upvotes: 2