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.
|
- Fix album size cache when photo reload metadata and generally improve that validation.
|
||||||
- Better bookmark url validation.
|
- Better bookmark url validation.
|
||||||
- Create a textbox which gives autocomplete tag names.
|
- 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
|
### 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.
|
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)
|
@functools.wraps(method)
|
||||||
def wrapped_transaction(self, *args, **kwargs):
|
def wrapped_transaction(self, *args, **kwargs):
|
||||||
photodb = _get_relevant_photodb(self)
|
photodb = _get_relevant_photodb(self)
|
||||||
photodb.savepoint()
|
savepoint_id = photodb.savepoint()
|
||||||
try:
|
try:
|
||||||
result = method(self, *args, **kwargs)
|
result = method(self, *args, **kwargs)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
photodb.rollback()
|
photodb.rollback(savepoint=savepoint_id)
|
||||||
raise
|
raise
|
||||||
else:
|
else:
|
||||||
return result
|
return result
|
||||||
|
|
|
@ -703,20 +703,27 @@ class PDBSQLMixin:
|
||||||
self.savepoints.clear()
|
self.savepoints.clear()
|
||||||
self.sql.commit()
|
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:
|
if len(self.savepoints) == 0:
|
||||||
self.log.debug('Nothing to rollback.')
|
self.log.debug('Nothing to rollback.')
|
||||||
return
|
return
|
||||||
|
|
||||||
if len(self.savepoints) == 1:
|
if valid_savepoint:
|
||||||
self.log.debug('Final rollback.')
|
restore_to = savepoint
|
||||||
self.sql.rollback()
|
while self.savepoints.pop(-1) != restore_to:
|
||||||
self.savepoints.clear()
|
pass
|
||||||
self.on_commit_queue.clear()
|
else:
|
||||||
return
|
restore_to = self.savepoints.pop(-1)
|
||||||
|
|
||||||
cur = self.sql.cursor()
|
cur = self.sql.cursor()
|
||||||
restore_to = self.savepoints.pop(-1)
|
|
||||||
self.log.debug('Rolling back to %s', restore_to)
|
self.log.debug('Rolling back to %s', restore_to)
|
||||||
query = 'ROLLBACK TO "%s"' % restore_to
|
query = 'ROLLBACK TO "%s"' % restore_to
|
||||||
cur.execute(query)
|
cur.execute(query)
|
||||||
|
|
Loading…
Reference in a new issue