Allow PDB.rollback to take a savepoint; Warn early commits.
If a @transaction method makes calls to other @transaction methods, and one of those nested calls makes a commit, and then the outer call raises an exception, then the outer call will not rollback properly because its savepoint is no longer in the savepoint stack. So let's warn the user if that happens. Should this raise an exception instead of just warn? Not sure, I mean the data is already committed.
This commit is contained in:
parent
26141f8198
commit
d88db08693
3 changed files with 18 additions and 10 deletions
|
@ -66,6 +66,7 @@ If you are interested in helping, please raise an issue before making any pull r
|
|||
- Fix album size cache when photo reload metadata and generally improve that validation.
|
||||
- Better bookmark url validation.
|
||||
- Create a textbox which gives autocomplete tag names.
|
||||
- Consider if the "did you commit too early" warning should actually be an exception.
|
||||
|
||||
### To do list: User permissions
|
||||
Here are some thoughts about the kinds of features that need to exist within the permission system. I don't know how I'll actually manage it just yet. Possibly a `permissions` table in the database with `user_id | permission` where `permission` is some reliably-formatted string.
|
||||
|
|
|
@ -72,11 +72,11 @@ def transaction(method):
|
|||
@functools.wraps(method)
|
||||
def wrapped_transaction(self, *args, **kwargs):
|
||||
photodb = _get_relevant_photodb(self)
|
||||
photodb.savepoint()
|
||||
savepoint_id = photodb.savepoint()
|
||||
try:
|
||||
result = method(self, *args, **kwargs)
|
||||
except Exception as e:
|
||||
photodb.rollback()
|
||||
photodb.rollback(savepoint=savepoint_id)
|
||||
raise
|
||||
else:
|
||||
return result
|
||||
|
|
|
@ -703,20 +703,27 @@ class PDBSQLMixin:
|
|||
self.savepoints.clear()
|
||||
self.sql.commit()
|
||||
|
||||
def rollback(self):
|
||||
def rollback(self, savepoint=None):
|
||||
if savepoint is not None:
|
||||
valid_savepoint = savepoint in self.savepoints
|
||||
else:
|
||||
valid_savepoint = None
|
||||
|
||||
if valid_savepoint is False:
|
||||
self.log.warn('Tried to restore to a nonexistent savepoint. Did you commit too early?')
|
||||
|
||||
if len(self.savepoints) == 0:
|
||||
self.log.debug('Nothing to rollback.')
|
||||
return
|
||||
|
||||
if len(self.savepoints) == 1:
|
||||
self.log.debug('Final rollback.')
|
||||
self.sql.rollback()
|
||||
self.savepoints.clear()
|
||||
self.on_commit_queue.clear()
|
||||
return
|
||||
if valid_savepoint:
|
||||
restore_to = savepoint
|
||||
while self.savepoints.pop(-1) != restore_to:
|
||||
pass
|
||||
else:
|
||||
restore_to = self.savepoints.pop(-1)
|
||||
|
||||
cur = self.sql.cursor()
|
||||
restore_to = self.savepoints.pop(-1)
|
||||
self.log.debug('Rolling back to %s', restore_to)
|
||||
query = 'ROLLBACK TO "%s"' % restore_to
|
||||
cur.execute(query)
|
||||
|
|
Loading…
Reference in a new issue