Manually increment revision numbers in revision plugin
Don't rely on the SQLAlchemy revision_col flag to bump revision numbers and instead bump them in a before_flush handler. This will allow the follow-up patch to do enforcement on conditional updates before the revision number is incremented. Partial-Bug: #1493714 Partially-Implements: blueprint push-notifications Change-Id: I5feeec5b8385727eff53dc669363bc41db8ceaba
This commit is contained in:
parent
72ac25c929
commit
9c0a0de556
@ -66,7 +66,8 @@ class StandardAttribute(model_base.BASEV2):
|
||||
__mapper_args__ = {
|
||||
# see http://docs.sqlalchemy.org/en/latest/orm/versioning.html for
|
||||
# details about how this works
|
||||
"version_id_col": revision_number
|
||||
"version_id_col": revision_number,
|
||||
"version_id_generator": False # revision plugin increments manually
|
||||
}
|
||||
|
||||
def bump_revision(self):
|
||||
|
@ -34,12 +34,16 @@ class RevisionPlugin(service_base.ServicePluginBase):
|
||||
def __init__(self):
|
||||
super(RevisionPlugin, self).__init__()
|
||||
db_api.sqla_listen(se.Session, 'before_flush', self.bump_revisions)
|
||||
db_api.sqla_listen(se.Session, 'after_commit',
|
||||
self._clear_rev_bumped_flags)
|
||||
db_api.sqla_listen(se.Session, 'after_rollback',
|
||||
self._clear_rev_bumped_flags)
|
||||
|
||||
def bump_revisions(self, session, context, instances):
|
||||
# bump revision number for any updated objects in the session
|
||||
for obj in session.dirty:
|
||||
if isinstance(obj, standard_attr.HasStandardAttributes):
|
||||
obj.bump_revision()
|
||||
self._bump_obj_revision(session, obj)
|
||||
|
||||
# see if any created/updated/deleted objects bump the revision
|
||||
# of another object
|
||||
@ -63,7 +67,7 @@ class RevisionPlugin(service_base.ServicePluginBase):
|
||||
self._bump_related_revisions(session, related_obj)
|
||||
# no need to bump revisions on related objects being deleted
|
||||
if related_obj not in session.deleted:
|
||||
related_obj.bump_revision()
|
||||
self._bump_obj_revision(session, related_obj)
|
||||
except exc.ObjectDeletedError:
|
||||
# object was in session but another writer deleted it
|
||||
pass
|
||||
@ -98,3 +102,20 @@ class RevisionPlugin(service_base.ServicePluginBase):
|
||||
"have load_on_pending set to True to "
|
||||
"bump parent revisions on create: %s"),
|
||||
relationship_col)
|
||||
|
||||
def _clear_rev_bumped_flags(self, session):
|
||||
"""This clears all flags on commit/rollback to enable rev bumps."""
|
||||
for inst in session:
|
||||
setattr(inst, '_rev_bumped', False)
|
||||
|
||||
def _bump_obj_revision(self, session, obj):
|
||||
"""Increment object revision in compare and swap fashion.
|
||||
|
||||
Before the increment, this checks and enforces any revision number
|
||||
constraints.
|
||||
"""
|
||||
if getattr(obj, '_rev_bumped', False):
|
||||
# we've already bumped the revision of this object in this txn
|
||||
return
|
||||
obj.bump_revision()
|
||||
setattr(obj, '_rev_bumped', True)
|
||||
|
@ -108,18 +108,18 @@ class TrunkTestJSON(TrunkTestJSONBase):
|
||||
@decorators.idempotent_id('4ce46c22-a2b6-4659-bc5a-0ef2463cab32')
|
||||
def test_create_update_trunk(self):
|
||||
trunk = self._create_trunk_with_network_and_parent(None)
|
||||
self.assertEqual(1, trunk['trunk']['revision_number'])
|
||||
rev = trunk['trunk']['revision_number']
|
||||
trunk_id = trunk['trunk']['id']
|
||||
res = self._show_trunk(trunk_id)
|
||||
self.assertTrue(res['trunk']['admin_state_up'])
|
||||
self.assertEqual(1, res['trunk']['revision_number'])
|
||||
self.assertEqual(rev, res['trunk']['revision_number'])
|
||||
self.assertEqual("", res['trunk']['name'])
|
||||
self.assertEqual("", res['trunk']['description'])
|
||||
res = self.client.update_trunk(
|
||||
trunk_id, name='foo', admin_state_up=False)
|
||||
self.assertFalse(res['trunk']['admin_state_up'])
|
||||
self.assertEqual("foo", res['trunk']['name'])
|
||||
self.assertGreater(res['trunk']['revision_number'], 1)
|
||||
self.assertGreater(res['trunk']['revision_number'], rev)
|
||||
# enable the trunk so that it can be managed
|
||||
self.client.update_trunk(trunk_id, admin_state_up=True)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user