Add the ability to soft_reset a workflow.
In cases where it is not desired to reset the whole state of the workflow, but only to soft_reset it so that it can be easily resumed from a interrupted state (for example). This change allows for that to happen, which involves also keeping track of the last task that ran so when resumed via soft_reset that task can be the one started off from (instead of starting from the start of all tasks). Change-Id: I034bd6af6445e3da52356328605368319c4ff6f9
This commit is contained in:
@@ -92,6 +92,9 @@ class Flow(object):
|
|||||||
self._state = states.PENDING
|
self._state = states.PENDING
|
||||||
# Tasks results are stored here...
|
# Tasks results are stored here...
|
||||||
self.results = []
|
self.results = []
|
||||||
|
# The last task index in the order we left off at before being
|
||||||
|
# interrupted (or failing).
|
||||||
|
self._left_off_at = 0
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def state(self):
|
def state(self):
|
||||||
@@ -129,6 +132,8 @@ class Flow(object):
|
|||||||
self._change_state(context, states.STARTED)
|
self._change_state(context, states.STARTED)
|
||||||
try:
|
try:
|
||||||
task_order = self.order()
|
task_order = self.order()
|
||||||
|
if self._left_off_at > 0:
|
||||||
|
task_order = task_order[self._left_off_at:]
|
||||||
except Exception:
|
except Exception:
|
||||||
with excutils.save_and_reraise_exception():
|
with excutils.save_and_reraise_exception():
|
||||||
try:
|
try:
|
||||||
@@ -160,6 +165,8 @@ class Flow(object):
|
|||||||
" object: %s", result)
|
" object: %s", result)
|
||||||
result = exc.InvalidStateException()
|
result = exc.InvalidStateException()
|
||||||
raise result
|
raise result
|
||||||
|
# Alter the index we have ran at.
|
||||||
|
self._left_off_at += 1
|
||||||
# Keep a pristine copy of the result
|
# Keep a pristine copy of the result
|
||||||
# so that if said result is altered by other further
|
# so that if said result is altered by other further
|
||||||
# states the one here will not be. This ensures that
|
# states the one here will not be. This ensures that
|
||||||
@@ -216,15 +223,33 @@ class Flow(object):
|
|||||||
self._change_state(context, states.SUCCESS)
|
self._change_state(context, states.SUCCESS)
|
||||||
|
|
||||||
def reset(self):
|
def reset(self):
|
||||||
# Reset all internal state (except our parent workflows).
|
# Reset (hard) alters the local state and does clear out other member
|
||||||
|
# variables state.
|
||||||
|
if self.state not in (states.INTERRUPTED, states.SUCCESS,
|
||||||
|
states.FAILURE, states.PENDING):
|
||||||
|
raise exc.InvalidStateException(("Can not reset when"
|
||||||
|
" in state %s") % (self.state))
|
||||||
self._state = states.PENDING
|
self._state = states.PENDING
|
||||||
self.results = []
|
self.results = []
|
||||||
self.task_listeners = []
|
self.task_listeners = []
|
||||||
self.listeners = []
|
self.listeners = []
|
||||||
self.result_fetcher = None
|
self.result_fetcher = None
|
||||||
self._accumulator.reset()
|
self._accumulator.reset()
|
||||||
|
self._left_off_at = 0
|
||||||
|
|
||||||
|
def soft_reset(self):
|
||||||
|
# Soft reset only alters the local state and does not clear out any
|
||||||
|
# other member variables state.
|
||||||
|
if self.state not in (states.INTERRUPTED, states.SUCCESS,
|
||||||
|
states.PENDING):
|
||||||
|
raise exc.InvalidStateException(("Can not soft_reset when"
|
||||||
|
" in state %s") % (self.state))
|
||||||
|
self._state = states.PENDING
|
||||||
|
|
||||||
def interrupt(self):
|
def interrupt(self):
|
||||||
|
if self.state in (states.FAILURE, states.SUCCESS, states.PENDING):
|
||||||
|
raise exc.InvalidStateException(("Can not interrupt when"
|
||||||
|
" in state %s") % (self.state))
|
||||||
self._change_state(None, states.INTERRUPTED)
|
self._change_state(None, states.INTERRUPTED)
|
||||||
|
|
||||||
def _change_state(self, context, new_state):
|
def _change_state(self, context, new_state):
|
||||||
|
Reference in New Issue
Block a user