[ZODB-Dev] transaction "Attempts" class
Chris McDonough
chrism at plope.com
Wed Mar 28 06:08:24 UTC 2012
The transaction package offers a nice feature, where you can say:
import transaction
for attempt in transaction.attempts(3):
with attempt as t:
... do something ...
If "do something" raises a ConflictError (or any other retryable error),
the next attempt is tried, until all attempts have been exhausted, at
which point, it gives up and the exception is raised.
But I think it may be slightly broken.
Here's the definition of the "attempt" context manager:
class Attempt(object):
def __init__(self, manager):
self.manager = manager
def __enter__(self):
return self.manager.__enter__()
def __exit__(self, t, v, tb):
if v is None:
self.manager.commit()
else:
retry = self.manager._retryable(t, v)
self.manager.abort()
return retry
"do_something" within the body of an "attempt" context manager usually
doesn't raise a retryable exception (it's business logic), but the
"self.manager.commit()" within the __exit__ of the context manager
usually does. When this happens, nothing actually catches the
exception. I think the context manager may need to be changed to this:
class Attempt(object):
def __init__(self, manager):
self.manager = manager
def __enter__(self):
return self.manager.__enter__()
def __exit__(self, t, v, tb):
if v is None:
try:
self.manager.commit()
except:
retry = self.manager._retryable(*sys.exc_info()[:2])
self.manager.abort()
return retry
else:
retry = self.manager._retryable(t, v)
self.manager.abort()
return retry
Either that or it needs to not try to do a commit itself, and leave it
up to the caller.
Anybody with thoughts?
- C
More information about the ZODB-Dev
mailing list