diff --git a/mistral/db/v2/api.py b/mistral/db/v2/api.py index f0ce2d430..8c4170de9 100644 --- a/mistral/db/v2/api.py +++ b/mistral/db/v2/api.py @@ -58,6 +58,10 @@ def transaction(): yield +def refresh(model): + IMPL.refresh(model) + + # Locking. diff --git a/mistral/db/v2/sqlalchemy/api.py b/mistral/db/v2/sqlalchemy/api.py index f2fcd61b2..e8bb9f72e 100644 --- a/mistral/db/v2/sqlalchemy/api.py +++ b/mistral/db/v2/sqlalchemy/api.py @@ -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 diff --git a/mistral/engine/tasks.py b/mistral/engine/tasks.py index c300772e1..52a8a8617 100644 --- a/mistral/engine/tasks.py +++ b/mistral/engine/tasks.py @@ -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):