#20571: Using savepoints within transaction.atomic() can result in the entire
transaction being incorrectly and silently rolled back
---------------------------------+---------------------------------------
     Reporter:  lamby            |                    Owner:  nobody
         Type:  Bug              |                   Status:  new
    Component:  Documentation    |                  Version:  1.6-alpha-1
     Severity:  Release blocker  |               Resolution:
     Keywords:                   |             Triage Stage:  Accepted
    Has patch:  0                |      Needs documentation:  0
  Needs tests:  0                |  Patch needs improvement:  0
Easy pickings:  0                |                    UI/UX:  0
---------------------------------+---------------------------------------

Comment (by akaariai):

 I was wrong in the above example, the second transaction.atomic() doesn't
 create any savepoints as the whole transaction needs to be rolled back
 anyways. Thus the needs_rollback flag isn't cleared.

 I updated the
 https://github.com/akaariai/django/compare/manual_savepoint_atomic patch.
 Now you can't create savepoints in failed blocks, so s2 in the example of
 comment:4 would fail. This seems good enough, there really isn't any point
 in creating a savepoint which is going to be rolled back anyways.

 As for do we need the ability to use manual savepoints? If possible, yes.
 Some things become nasty to code if your only option is using exceptions.
 Say, you call a method, and if that method returns false you will need to
 rollback the current savepoint. Options:
 {{{
 def myf():
     sp = savepoint()
     if somemethod():
         savepoint_commit()
     else:
         savepoint_rollback()

 def myf():
     try:
         with atomic():
             if somemethod():
                 return
             else:
                 raise FakeException  # This will now rollback the
 savepoint.
     except FakeException:
         return
 }}}

 Another situation where atomic() isn't easy is if you have different paths
 for enter and exit. Then naturally any with statement can't be used. An
 example is TransactionMiddleware.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/20571#comment:7>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/063.cc2a3853b62ae0d4f0fcfbffea35efce%40djangoproject.com?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to