Check the revision number only once

When an OVO revision number transaction constraint is requested
in the HTTP header, the OVO standard attributes revision number
should be checked only once, because:
- The revision number constrain refers to a single resource; only
  a single check is needed.
- Some backends (OVN), execute more than one DB transaction.
  As reported in the related LP bug, the second time the OVO is
  checked during the second DB transaction, the revision number of
  the OVO has been bumped and does not match with the original
  number requested.

Closes-Bug: #1909008

Change-Id: I25c36b1604e5855a22960f1b504a79f740c134bb
This commit is contained in:
Rodolfo Alonso Hernandez 2021-01-05 12:29:46 +00:00
parent b2389a31a0
commit 6b0ae48381
2 changed files with 18 additions and 1 deletions

View File

@ -259,7 +259,12 @@ class RevisionPlugin(service_base.ServicePluginBase):
to match.
"""
context = session.info.get('using_context')
criteria = context.get_transaction_constraint() if context else None
if context:
# NOTE(ralonsoh): use "pop_transaction_constraint" once implemented
criteria = context.get_transaction_constraint()
context.clear_transaction_constraint()
else:
criteria = None
if not criteria:
return None, None
match = criteria.if_revision_match

View File

@ -155,8 +155,20 @@ class TestRevisionPlugin(test_plugin.Ml2PluginV2TestCase):
raise db_exc.DBDeadlock()
db_api.sqla_listen(se.Session, 'before_commit',
concurrent_increment)
# Despite the revision number is bumped twice during the session
# transaction, the revision number is tested only once the first
# time the revision number service is executed for this session and
# object.
self._update('ports', port['port']['id'], new,
headers={'If-Match': 'revision_number=%s' % rev},
expected_code=exc.HTTPOk.code)
self._update('ports', port['port']['id'], new,
headers={'If-Match': 'revision_number=%s' %
str(int(rev) + 2)},
expected_code=exc.HTTPOk.code)
self._update('ports', port['port']['id'], new,
headers={'If-Match': 'revision_number=1'},
expected_code=exc.HTTPPreconditionFailed.code)
def test_port_ip_update_revises(self):