Add the task to the accumulator before running.

Instead of only adding the task to the rollback
accumulator after it has ran it is useful to add
it to the accumulator before it runs so that if
said task fails while running it can get a chance
at undoing anything it might have done.

Change-Id: I5c9cf2fd194e3b42639d84a0d9dfed3a3b5a797d
This commit is contained in:
Joshua Harlow
2013-06-07 17:25:45 -07:00
parent b94b4f0412
commit 17c5e6e734

View File

@@ -145,6 +145,11 @@ class Flow(object):
def run_task(task, failed=False, result=None, simulate_run=False):
try:
self._on_task_start(context, task)
# Add the task to be rolled back *immediately* so that even if
# the task fails while producing results it will be given a
# chance to rollback.
rb = RollbackTask(context, task, result=None)
self._accumulator.add(rb)
if not simulate_run:
inputs = self._fetch_task_inputs(task)
if not inputs:
@@ -165,21 +170,25 @@ class Flow(object):
" object: %s", result)
result = exc.InvalidStateException()
raise result
# Alter the index we have ran at.
self._left_off_at += 1
# Keep a pristine copy of the result
# so that if said result is altered by other further
# states the one here will not be. This ensures that
# if rollback occurs that the task gets exactly the
# result it returned and not a modified one.
self.results.append((task, result))
# Add the task result to the accumulator before
# Adjust the task result in the accumulator before
# notifying others that the task has finished to
# avoid the case where a listener might throw an
# exception.
self._accumulator.add(RollbackTask(context, task,
copy.deepcopy(result)))
self._on_task_finish(context, task, result)
#
# Note(harlowja): Keep the original result in the
# accumulator only and give a duplicated copy to
# avoid the original result being altered by other
# tasks.
#
# This is due to python being by reference (which means
# some task could alter this result intentionally or not
# intentionally).
rb.result = result
# Alter the index we have ran at.
self._left_off_at += 1
result_copy = copy.deepcopy(result)
self.results.append((task, result_copy))
self._on_task_finish(context, task, result_copy)
except Exception as e:
cause = FlowFailure(task, self, e)
with excutils.save_and_reraise_exception():