Add worms.raise_without_rollback.
This commit is contained in:
parent
0fd09984bc
commit
38f9d8046c
1 changed files with 24 additions and 2 deletions
|
@ -26,14 +26,28 @@ class DeletedObject(WormException):
|
||||||
'''
|
'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
# snake-cased because I want the ergonomics of a function from the caller's end.
|
||||||
|
class raise_without_rollback:
|
||||||
|
def __init__(self, exc):
|
||||||
|
self.exc = exc
|
||||||
|
|
||||||
def slice_before(li, item):
|
def slice_before(li, item):
|
||||||
index = li.index(item)
|
index = li.index(item)
|
||||||
return li[:index]
|
return li[:index]
|
||||||
|
|
||||||
def transaction(method):
|
def transaction(method):
|
||||||
'''
|
'''
|
||||||
Open a savepoint before running the method.
|
This decorator can be added to functions that modify your worms database.
|
||||||
If the method fails, roll back to that savepoint.
|
A savepoint is opened, then your function is run, then we roll back to the
|
||||||
|
savepoint if an exception is raised.
|
||||||
|
|
||||||
|
This decorator adds the keyword argument 'commit' to your function, so that
|
||||||
|
callers can commit it immediately.
|
||||||
|
|
||||||
|
If you want to raise an exception without rolling back, you can return
|
||||||
|
worms.raise_without_rollback(exc). This could be useful if you want to
|
||||||
|
preserve some kind of attempted action in the database while still raising
|
||||||
|
the action's failure.
|
||||||
'''
|
'''
|
||||||
@functools.wraps(method)
|
@functools.wraps(method)
|
||||||
def wrapped_transaction(self, *args, commit=False, **kwargs):
|
def wrapped_transaction(self, *args, commit=False, **kwargs):
|
||||||
|
@ -52,9 +66,17 @@ def transaction(method):
|
||||||
database.rollback(savepoint=savepoint_id)
|
database.rollback(savepoint=savepoint_id)
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
if isinstance(result, raise_without_rollback):
|
||||||
|
raise result.exc from result.exc
|
||||||
|
|
||||||
if commit:
|
if commit:
|
||||||
database.commit(message=method.__qualname__)
|
database.commit(message=method.__qualname__)
|
||||||
elif not is_root:
|
elif not is_root:
|
||||||
|
# In order to prevent a huge pile-up of savepoints when a
|
||||||
|
# @transaction calls another @transaction many times, the sub-call
|
||||||
|
# savepoints are removed from the stack. When an exception occurs,
|
||||||
|
# we're going to rollback from the rootmost savepoint anyway, we'll
|
||||||
|
# never rollback one sub-transaction.
|
||||||
database.release_savepoint(savepoint=savepoint_id)
|
database.release_savepoint(savepoint=savepoint_id)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue