From ac1472c8cffe64d32a012c73227595f2f7806de9 Mon Sep 17 00:00:00 2001 From: Jakub Libosvar Date: Tue, 7 May 2024 20:03:14 +0000 Subject: [PATCH] Don't update revision number if object was not modified If there were not changes made to data in the database there is no reason to bump revision numbers because the underlying drivers won't change too. This saves cycles in case empty updates are incoming to the API. Co-Authored-By: Ihar Hrachyshka Closes-bug: #2065094 Change-Id: Ib74fdab7a8927ef9cc24ef7810e9cf2c264941eb (cherry picked from commit 5795c192b840ae327bc9e32d5183f177daa9b55b) --- neutron/services/revisions/revision_plugin.py | 6 +++--- .../tests/unit/services/revisions/test_revision_plugin.py | 5 ++++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/neutron/services/revisions/revision_plugin.py b/neutron/services/revisions/revision_plugin.py index 24e2e7f7f7e..28e5e91c904 100644 --- a/neutron/services/revisions/revision_plugin.py +++ b/neutron/services/revisions/revision_plugin.py @@ -78,14 +78,14 @@ class RevisionPlugin(service_base.ServicePluginBase): def bump_revisions(self, session, context, instances): self._enforce_if_match_constraints(session) # bump revision number for updated objects in the session + modified_objs = {o for o in session.dirty if session.is_modified(o)} self._bump_obj_revisions( - session, - self._get_objects_to_bump_revision(session.dirty)) + session, self._get_objects_to_bump_revision(modified_objs)) # see if any created/updated/deleted objects bump the revision # of another object objects_with_related_revisions = [ - o for o in session.deleted | session.dirty | session.new + o for o in modified_objs | set(session.deleted) | set(session.new) if getattr(o, 'revises_on_change', ()) ] collected = session.info.setdefault('_related_bumped', set()) diff --git a/neutron/tests/unit/services/revisions/test_revision_plugin.py b/neutron/tests/unit/services/revisions/test_revision_plugin.py index 8f5ae05916d..7d9cc9a5ddd 100644 --- a/neutron/tests/unit/services/revisions/test_revision_plugin.py +++ b/neutron/tests/unit/services/revisions/test_revision_plugin.py @@ -143,13 +143,13 @@ class TestRevisionPlugin(test_plugin.Ml2PluginV2TestCase): # update with self.port() as port: rev = port['port']['revision_number'] - new = {'port': {'name': 'nigiri'}} def concurrent_increment(s): db_api.sqla_remove(se.Session, 'before_commit', concurrent_increment) # slip in a concurrent update that will bump the revision plugin = directory.get_plugin() + new = {'port': {'name': 'nigiri'}} plugin.update_port(nctx.get_admin_context(), port['port']['id'], new) raise db_exc.DBDeadlock() @@ -160,13 +160,16 @@ class TestRevisionPlugin(test_plugin.Ml2PluginV2TestCase): # transaction, the revision number is tested only once the first # time the revision number service is executed for this session and # object. + new = {'port': {'name': 'sushi'}} self._update('ports', port['port']['id'], new, headers={'If-Match': 'revision_number=%s' % rev}, expected_code=exc.HTTPOk.code) + new = {'port': {'name': 'salmon'}} self._update('ports', port['port']['id'], new, headers={'If-Match': 'revision_number=%s' % str(int(rev) + 2)}, expected_code=exc.HTTPOk.code) + new = {'port': {'name': 'tea'}} self._update('ports', port['port']['id'], new, headers={'If-Match': 'revision_number=1'}, expected_code=exc.HTTPPreconditionFailed.code)