Commit 88ded86e authored by Alec Mitchell's avatar Alec Mitchell

Call setDefaultSkin on new requests created as the result of ConflictError...

Call setDefaultSkin on new requests created as the result of ConflictError retries.  This allows view lookups to continue to work during retry attempts.
parent f2a9d260
......@@ -8,6 +8,9 @@ Zope Changes
Bugs fixed
- Call setDefaultSkin on new requests created as the result of
ConflictError retries.
- Collector #2189: Fix logging of errors during product refresh.
- Collector #2185: Log username for FCGI requests.
......
......@@ -159,6 +159,8 @@ def publish(request, module_name, after_list, debug=0,
# Only reachable if Retry is raised and request supports retry.
newrequest=request.retry()
request.close() # Free resources held by the request.
# Set the default layer/skin on the newly generated request
setDefaultSkin(newrequest)
try:
return publish(newrequest, module_name, after_list, debug)
finally:
......
from zope.app.publication.browser import setDefaultSkin
from zope.publisher.interfaces.browser import IDefaultBrowserLayer
from ZPublisher import Retry
from ZODB.POSException import ConflictError
......@@ -118,6 +120,14 @@ class Request:
r.retry_count = self.retry_count
return r
class RequestWithSkinCheck(Request):
def traverse(self, path, validated_hook):
if IDefaultBrowserLayer.providedBy(self):
return Object()
else:
tracer.exceptions['__call__'] = [ValueError]
return Object()
module_name = __name__
after_list = [None]
......@@ -263,6 +273,56 @@ def testPublisher():
raising ConflictError from zpublisher_exception_hook
abort
The request generator applies the default skin layer to the request.
We have a specially crafted request that tests this. If the
request does not have the required interface it raises an
ValueError. Let's see that this works as expected
>>> tracer.reset()
>>> request = RequestWithSkinCheck()
>>> setDefaultSkin(request)
>>> response = publish(request, module_name, after_list)
>>> tracer.showTracedPath()
begin
__call__
commit
Retries generate new request objects, the publisher needs to
ensure that the skin layer is applied to those as well. If the
skin layer is not applied to subsequent requests, an ValueError
would be raised here.
>>> tracer.reset()
>>> tracer.exceptions['commit'] = [ConflictError, ConflictError,
... ConflictError, ConflictError]
>>> request = RequestWithSkinCheck()
>>> setDefaultSkin(request)
>>> response = publish(request, module_name, after_list)
Traceback (most recent call last):
...
ConflictError: database conflict error
>>> tracer.showTracedPath()
begin
__call__
commit
raising ConflictError from commit
abort
begin
__call__
commit
raising ConflictError from commit
abort
begin
__call__
commit
raising ConflictError from commit
abort
begin
__call__
commit
raising ConflictError from commit
abort
"""
pass
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment