[Zope-dev] [Bug] Zope's transaction behaviour flawed

Steve Alexander steve@cat-box.net
Mon, 03 Feb 2003 10:44:46 +0200


Chris McDonough wrote:
> I am +1 on this.  I suspect that before committing, though, we should
>  ask people who make use of Zope's transaction manager in "advanced"
> ways like Phillip Eby.

As I noted in the Collector issue, I believe this change is a good idea
overall. As Chris suggests, we should take note of users of ZPatterns 
and TransactionAgents (and other add-ons?), as these do things at 
transaction boundaries such as clear computed fields. The error handlers 
currently in use may expect these computed fields to be still available.


By conincidence I'm implementing something similar for error handling in 
Zope 3 right now.

Here's the kind of thing I'm doing in zope 3, using the same notation 
Dieter used. First, the simple case where the error handler will 
definitely not need to alter any state:

   ## request starts
   transaction.begin()
   try:
       object= REQUEST.traverse(...)
       result = mapply(object,...)
       transaction.commit()
   except:
       try:
           try:
                result = handle_error()
           except:
                result = default_handle_error()
                # Zope's default error handling
                # it must not have side effects
       finally:
           transaction.abort()
   request.response.setBody(result)
   ## request ends

If there's an exception handler that has side-effects, it must 
explicitly say so, and we get this:

   ## request starts
   transaction.begin()
   try:
       object= REQUEST.traverse(...)
       result = mapply(object,...)
       transaction.commit()
   except:
       try:
           try:
                # this call returns a special
                # 'I have side-effects' token.
                result = handle_error()
           except:
                result = default_handle_error()
                # Zope's default error handling
                # it should not have side effects
       finally:
           transaction.abort()

   if result is I_HAVE_SIDE_EFFECTS:
       transaction.begin()
       transaction.note('%s (application error handling)'
                        % '/'.join(object.getPhysicalPath))
       try:
           result = handle_error_with_sideeffects()
           transaction.commit()
       except:
           try:
               result = default_handle_error()
               # Zope's default error handling
               # it should not have side effects
           finally:
               transaction.abort()
   else:
       request.response.setBody(result)
   ## request ends

--
Steve Alexander