#2227: atch] transaction.commit()/rollback() should be aware of nested calls to
transaction.managed(True)
---------------------------------------------------+------------------------
          Reporter:  md...@yandex.ru               |         Owner:  nobody     
             
            Status:  assigned                      |     Milestone:             
             
         Component:  Database layer (models, ORM)  |       Version:  SVN        
             
        Resolution:                                |      Keywords:  
transaction, nest, scope
             Stage:  Accepted                      |     Has_patch:  1          
             
        Needs_docs:  0                             |   Needs_tests:  0          
             
Needs_better_patch:  0                             |  
---------------------------------------------------+------------------------
Comment (by Glenn):

 This seems like a step in the right direction, but not being allowed to
 call rollback() from within a nested transaction seems like a killer.
 What are you supposed to do?  You'd have to remember that you aren't the
 top-level transaction level, raise an exception instead of rolling back,
 and expect whoever is the top-level transaction to rollback for you once
 the exception propagates out.

 That's very brittle.  If someone accidentally eats the exception before it
 gets there, then the transaction might be committed, which is the worst
 possible failure mode.

 Instead, I'd suggest:

  - when rollback is called when nested, mark the transaction failed;
  - if commit is called when not nested and the transaction was marked
 failed, raise an exception, because rollback should have been called
 instead.

 This allows calling rollback() to cancel the transaction, and guarantees
 that the transaction will never be committed, which I think is a critical
 invariant.

 Then, this would work (easily dropped into a decorator):

 {{{
 def foo():
     transaction.enter_transaction_management()
     try:
         # code

         transaction.set_dirty()
         transaction.commit()
     except:
         transaction.rollback()
         raise
     finally:
         transaction.leave_transaction_management()

 def fum():
     transaction.enter_transaction_management()
     try:
         foo()
     except:
         transaction.rollback()
         raise
     finally:
         transaction.leave_transaction_management()
 }}}

-- 
Ticket URL: <http://code.djangoproject.com/ticket/2227#comment:17>
Django <http://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 post to this group, send email to django-updates@googlegroups.com
To unsubscribe from this group, send email to 
django-updates+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to