Refresh object state after lock acquisition in WithItemsTask

* We need to refresh task state once we acquired the 'with-items'
  lock to prevent modifying stale values cached by SQLAlchemy
  session. For this purpose, new DB API method refresh() was
  added. Without this change 'with-items' task doesn't work
  properly in case of using multiple engines.

Change-Id: Id5a1d2cf03090279e6df3805562e00d300b89953
Closes-Bug: #1640378
Partial-Bug: #1640379
This commit is contained in:
Renat Akhmerov 2016-12-21 12:30:34 +07:00
parent aeb3ac5b1e
commit 62862ca0b7
3 changed files with 17 additions and 0 deletions

View File

@ -58,6 +58,10 @@ def transaction():
yield
def refresh(model):
IMPL.refresh(model)
# Locking.

View File

@ -115,6 +115,11 @@ def transaction():
end_tx()
@b.session_aware()
def refresh(model, session=None):
session.refresh(model)
@b.session_aware()
def acquire_lock(model, id, session=None):
# Expire all so all objects queried after lock is acquired

View File

@ -438,6 +438,14 @@ class WithItemsTask(RegularTask):
# from modifying runtime context simultaneously by multiple
# transactions.
with db_api.named_lock('with-items-%s' % self.task_ex.id):
# NOTE: We need to refresh task execution object right
# after the lock is acquired to make sure that we're
# working with a fresh state of its runtime context.
# Otherwise, SQLAlchemy session can contain a stale
# cached version of it so that we don't modify actual
# values (i.e. capacity).
db_api.refresh(self.task_ex)
self._on_action_complete(action_ex)
def _on_action_complete(self, action_ex):