Make it easier to raise retryable exceptions

Bug #137905 reported by James Henstridge
2
Affects Status Importance Assigned to Milestone
zope.publisher
Invalid
Undecided
Unassigned

Bug Description

If I want an exception I raise to cause the request to be retried, I've got two choices:

 1. manually wrap it in a Retry exception at the point where I raise it
 2. update my publication class's handleException() to covert the exception to a retry (provided retry_allowed=True).

The first option is useful since it lets the retry behaviour be defined at the point where the exception is raised or defined. However, getOriginalException() will return a very shallow stack trace making debugging difficult.

The second option gives us full stack traces, but may not be an option for a general purpose library.

It would be nice if the default ZopePublication.handleException() method checked for a marker interface on the exception value (IRetryable maybe?) and converted such exceptions into Retry exceptions.

Revision history for this message
Christian Theune (ctheune) wrote : Re: [Bug 137905] Make it easier to raise retryable exceptions

Sounds reasonable to me. Is the situation where you need that an
exception that is database related but you don't use ZODB?

Revision history for this message
James Henstridge (jamesh) wrote :

Yes. The use case I had in mind were SQL database exceptions (integrity errors, database disconnections, etc).

I'd imagine that such a feature would remove the need for ZopePublication to explicitly check for ZODB's ConflictError -- just make ConflictError implement the appropriate marker interface.

Revision history for this message
Christian Theune (ctheune) wrote : Re: [Bug 137905] Re: Make it easier to raise retryable exceptions

Am Freitag, den 07.09.2007, 07:02 +0000 schrieb James Henstridge:
> Yes. The use case I had in mind were SQL database exceptions (integrity
> errors, database disconnections, etc).
>
> I'd imagine that such a feature would remove the need for
> ZopePublication to explicitly check for ZODB's ConflictError -- just
> make ConflictError implement the appropriate marker interface.

Right. My suspicion was that the publication is a bit too much tied to
the ZODB here.

Changed in zope3:
status: New → Confirmed
Revision history for this message
Jim Fulton (jim-zope) wrote : Re: [Bug 137905] Make it easier to raise retryable exceptions

I haven't looked at this, but ... :)

I wonder if this could be handled by an error view. Currently, the
publication gets a view on the error to generate the error page.
Perhaps the view could generate a retry exception. I think this
would be cleaner than checking for a marker interface.

Jim

On Sep 7, 2007, at 2:21 AM, James Henstridge wrote:

> Public bug reported:
>
> If I want an exception I raise to cause the request to be retried,
> I've
> got two choices:
>
> 1. manually wrap it in a Retry exception at the point where I
> raise it
> 2. update my publication class's handleException() to covert the
> exception to a retry (provided retry_allowed=True).
>
> The first option is useful since it lets the retry behaviour be
> defined
> at the point where the exception is raised or defined. However,
> getOriginalException() will return a very shallow stack trace making
> debugging difficult.
>
> The second option gives us full stack traces, but may not be an option
> for a general purpose library.
>
> It would be nice if the default ZopePublication.handleException()
> method
> checked for a marker interface on the exception value (IRetryable
> maybe?) and converted such exceptions into Retry exceptions.

--
Jim Fulton mailto:<email address hidden> Python Powered!
CTO (540) 361-1714 http://www.python.org
Zope Corporation http://www.zope.com http://www.zope.org

Revision history for this message
Gustavo Niemeyer (niemeyer) wrote :

Performing this task with a view certainly sounds doable, but I wonder
if it's the right thing to do.

This would mean that the logic for retrying a transaction would be a
responsibility of the view that is supposed to display the error (errors
can't be retried forever), which is also dependent on the skin being
used.

The explicitness of the marking approach and the way that it separates
viewing from request retry logic sound like a good thing.

Revision history for this message
James Henstridge (jamesh) wrote :

I guess this is the sort of view class Jim has in mind.

    class DisconnectionErrorView:

        def __init__(self, context, request):
            self.context = context
            self.request = request

        def __call__(self):
            # If retries are allowed, raise a Retry exception
            if self.request.supportsRetry():
                raise Retry(sys.exc_info())
            # Otherwise, show an error page to the user
            return 'Disconnected!'

When I gave this view a go in a case where the corresponding exception would be raised once, I saw three exceptions logged: on DisconnectionError (with a full stack trace up to the publication level, which is good) followed by two Retry exceptions wrapping a DisconnectionError. I got the fallback "A server error occurred" error page, rather than the custom error page I wanted to see. There isn't any indication that the request was retried (if it was, it would have completed without raising DisconnectionErrror

By catching the exception in the publication's handleException() method instead (as is done for ConflictError), the request got retried correctly and rendered on the second attempt.

I haven't tested this with the most recent zope3 code, but even if it works it isn't clear that it solves the problem since it ties the retry behaviour together with the presentation of the error to the user in the case of continued failures. This is a problem for a library that would like to mark certain errors as requiring a retry, while letting applications customise the presentation of those errors (as a database adapter might want to do for disconnection errors). The marker interface solution wouldn't suffer from this problem.

affects: zope3 → zope.publisher
Revision history for this message
Colin Watson (cjwatson) wrote :

The zope.publisher project on Launchpad has been archived at the request of the Zope developers (see https://answers.launchpad.net/launchpad/+question/683589 and https://answers.launchpad.net/launchpad/+question/685285). If this bug is still relevant, please refile it at https://github.com/zopefoundation/zope.publisher.

Changed in zope.publisher:
status: Confirmed → Invalid
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.