def complete_task(task_ex, state, state_info): task = _build_task_from_execution( spec_parser.get_workflow_spec_by_id(task_ex.workflow_id), task_ex ) try: task.complete(state, state_info) except exc.MistralException as e: wf_ex = task_ex.workflow_execution msg = ( "Failed to complete task [wf=%s, task=%s]: %s\n%s" % (wf_ex, task_ex.name, e, tb.format_exc()) ) LOG.error(msg) task.set_state(states.ERROR, msg) wf_handler.fail_workflow(wf_ex, msg) return if task.is_completed(): wf_handler.on_task_complete(task_ex)
def run_task(wf_cmd): """Runs workflow task. :param wf_cmd: Workflow command. """ task = _build_task_from_command(wf_cmd) try: task.run() except exc.MistralException as e: wf_ex = wf_cmd.wf_ex task_spec = wf_cmd.task_spec msg = ( "Failed to run task [wf=%s, task=%s]: %s\n%s" % (wf_ex, task_spec.get_name(), e, tb.format_exc()) ) LOG.error(msg) task.set_state(states.ERROR, msg) wf_handler.fail_workflow(wf_ex, msg) return if task.is_completed(): wf_handler.on_task_complete(task.task_ex)
def run_task(wf_cmd): """Runs workflow task. :param wf_cmd: Workflow command. """ task = _build_task_from_command(wf_cmd) try: task.run() except exc.MistralException as e: wf_ex = wf_cmd.wf_ex task_spec = wf_cmd.task_spec msg = ("Failed to run task [wf=%s, task=%s]: %s\n%s" % (wf_ex, task_spec.get_name(), e, tb.format_exc())) LOG.error(msg) task.set_state(states.ERROR, msg) wf_handler.fail_workflow(wf_ex, msg) return if task.is_completed(): wf_handler.on_task_complete(task.task_ex)
def continue_task(task_ex): wf_spec = spec_parser.get_workflow_spec_by_execution_id( task_ex.workflow_execution_id) task = _build_task_from_execution(wf_spec, task_ex) try: task.set_state(states.RUNNING, None) task.run() except exc.MistralException as e: wf_ex = task_ex.workflow_execution msg = ("Failed to run task [wf=%s, task=%s]: %s\n%s" % (wf_ex, task_ex.name, e, tb.format_exc())) LOG.error(msg) task.set_state(states.ERROR, msg) wf_handler.fail_workflow(wf_ex, msg) return if task.is_completed(): wf_handler.schedule_on_task_complete(task_ex)
def fail_task(task_ex, msg): task = _build_task_from_execution( spec_parser.get_workflow_spec_by_id(task_ex.workflow_id), task_ex ) task.set_state(states.ERROR, msg) wf_handler.fail_workflow(task_ex.workflow_execution, msg)
def _stop_workflow(wf_ex, state, message=None): if state == states.SUCCESS: wf_ctrl = wf_base.get_controller(wf_ex) final_context = {} try: final_context = wf_ctrl.evaluate_workflow_final_context() except Exception as e: LOG.warning( 'Failed to get final context for %s: %s' % (wf_ex, e) ) wf_spec = spec_parser.get_workflow_spec(wf_ex.spec) return wf_handler.succeed_workflow( wf_ex, final_context, wf_spec, message ) elif state == states.ERROR: return wf_handler.fail_workflow(wf_ex, message) return wf_ex
def _check_workflow_completion(wf_ex, wf_ctrl): if states.is_paused_or_completed(wf_ex.state): return if wf_utils.find_incomplete_task_executions(wf_ex): return if wf_ctrl.all_errors_handled(): wf_handler.succeed_workflow( wf_ex, wf_ctrl.evaluate_workflow_final_context() ) else: state_info = wf_utils.construct_fail_info_message(wf_ctrl, wf_ex) wf_handler.fail_workflow(wf_ex, state_info)
def _check_workflow_completion(wf_ex, action_ex, wf_ctrl): if states.is_paused_or_completed(wf_ex.state): return if wf_utils.find_incomplete_tasks(wf_ex): return if wf_ctrl.all_errors_handled(): wf_handler.succeed_workflow( wf_ex, wf_ctrl.evaluate_workflow_final_context()) else: result_str = (str(action_ex.output.get('result', 'Unknown')) if action_ex.output else 'Unknown') state_info = ("Failure caused by error in task '%s': %s" % (action_ex.task_execution.name, result_str)) wf_handler.fail_workflow(wf_ex, state_info)
def on_action_complete(action_ex): """Handles action completion event. :param action_ex: Action execution. """ task_ex = action_ex.task_execution if not task_ex: return task_spec = spec_parser.get_task_spec(task_ex.spec) wf_ex = task_ex.workflow_execution task = _create_task( wf_ex, task_spec, task_ex.in_context, task_ex ) try: task.on_action_complete(action_ex) except exc.MistralException as e: task_ex = action_ex.task_execution wf_ex = task_ex.workflow_execution msg = ("Failed to handle action completion [wf=%s, task=%s," " action=%s]: %s\n%s" % (wf_ex.name, task_ex.name, action_ex.name, e, tb.format_exc())) LOG.error(msg) task.set_state(states.ERROR, msg) wf_handler.fail_workflow(wf_ex, msg) return if task.is_completed(): wf_handler.on_task_complete(task_ex)
def on_action_complete(action_ex): """Handles action completion event. :param action_ex: Action execution. """ task_ex = action_ex.task_execution if not task_ex: return task_spec = spec_parser.get_task_spec(task_ex.spec) wf_ex = task_ex.workflow_execution task = _create_task( wf_ex, spec_parser.get_workflow_spec_by_id(wf_ex.workflow_id), task_spec, task_ex.in_context, task_ex ) try: task.on_action_complete(action_ex) except exc.MistralException as e: wf_ex = task_ex.workflow_execution msg = ("Failed to handle action completion [wf=%s, task=%s," " action=%s]: %s\n%s" % (wf_ex.name, task_ex.name, action_ex.name, e, tb.format_exc())) LOG.error(msg) task.set_state(states.ERROR, msg) wf_handler.fail_workflow(wf_ex, msg) return if task.is_completed(): wf_handler.on_task_complete(task_ex)
def _dispatch_workflow_commands(self, wf_ex, wf_cmds, wf_spec): if not wf_cmds: return for cmd in wf_cmds: if isinstance(cmd, commands.RunTask) and cmd.is_waiting(): task_handler.defer_task(cmd) elif isinstance(cmd, commands.RunTask): task_ex = task_handler.run_new_task(cmd, wf_spec) if task_ex.state == states.ERROR: wf_handler.fail_workflow( wf_ex, 'Failed to start task [task_ex=%s]: %s' % (task_ex, task_ex.state_info) ) elif isinstance(cmd, commands.RunExistingTask): task_ex = task_handler.run_existing_task( cmd.task_ex.id, reset=cmd.reset ) if task_ex.state == states.ERROR: wf_handler.fail_workflow( wf_ex, 'Failed to start task [task_ex=%s]: %s' % (task_ex, task_ex.state_info) ) elif isinstance(cmd, commands.SetWorkflowState): if states.is_completed(cmd.new_state): self._stop_workflow(cmd.wf_ex, cmd.new_state, cmd.msg) else: wf_handler.set_execution_state(wf_ex, cmd.new_state) elif isinstance(cmd, commands.Noop): # Do nothing. pass else: raise RuntimeError('Unsupported workflow command: %s' % cmd) if wf_ex.state != states.RUNNING: break
def _check_workflow_completion(wf_ex, action_ex, wf_ctrl): if states.is_paused_or_completed(wf_ex.state): return if wf_utils.find_incomplete_tasks(wf_ex): return if wf_ctrl.all_errors_handled(): wf_handler.succeed_workflow( wf_ex, wf_ctrl.evaluate_workflow_final_context() ) else: result_str = str(action_ex.output.get('result', "Unknown")) state_info = ( "Failure caused by error in task '%s': %s" % (action_ex.task_execution.name, result_str) ) wf_handler.fail_workflow(wf_ex, state_info)
def _check_workflow_completion(wf_ex, wf_ctrl): if states.is_paused_or_completed(wf_ex.state): return # Workflow is not completed if there are any incomplete task # executions that are not in WAITING state. If all incomplete # tasks are waiting and there are unhandled errors, then these # tasks will not reach completion. In this case, mark the # workflow complete. incomplete_tasks = wf_utils.find_incomplete_task_executions(wf_ex) if any(not states.is_waiting(t.state) for t in incomplete_tasks): return if wf_ctrl.all_errors_handled(): wf_handler.succeed_workflow( wf_ex, wf_ctrl.evaluate_workflow_final_context()) else: state_info = wf_utils.construct_fail_info_message(wf_ctrl, wf_ex) wf_handler.fail_workflow(wf_ex, state_info)
def run_task(wf_cmd): """Runs workflow task. :param wf_cmd: Workflow command. """ task = _build_task_from_command(wf_cmd) try: task.run() except exc.MistralException as e: wf_ex = wf_cmd.wf_ex task_spec = wf_cmd.task_spec msg = ("Failed to run task [wf=%s, task=%s]: %s\n%s" % (wf_ex, task_spec.get_name(), e, tb.format_exc())) LOG.error(msg) task.set_state(states.ERROR, msg) wf_handler.fail_workflow(wf_ex, msg) return if not task.task_ex: # It is possible that task execution was not created # (and therefore not associated with Task instance). # For example, in case of 'join' that has already been # created by a different transaction. In this case # we should skip post completion scheduled checks. return if task.is_waiting(): _schedule_refresh_task_state(task.task_ex) if task.is_completed(): wf_handler.schedule_on_task_complete(task.task_ex)
def _on_task_state_change(self, task_ex, wf_ex, wf_spec): task_spec = wf_spec.get_tasks()[task_ex.name] if task_handler.is_task_completed(task_ex, task_spec): task_handler.after_task_complete(task_ex, task_spec, wf_spec) # Ignore DELAYED state. if task_ex.state == states.RUNNING_DELAYED: return wf_ctrl = wf_base.get_controller(wf_ex, wf_spec) # Calculate commands to process next. try: cmds = wf_ctrl.continue_workflow() except exc.YaqlEvaluationException as e: LOG.error( 'YAQL error occurred while calculating next workflow ' 'commands [wf_ex_id=%s, task_ex_id=%s]: %s', wf_ex.id, task_ex.id, e ) wf_handler.fail_workflow(wf_ex, str(e)) return # Mark task as processed after all decisions have been made # upon its completion. task_ex.processed = True self._dispatch_workflow_commands(wf_ex, cmds, wf_spec) self._check_workflow_completion(wf_ex, wf_ctrl, wf_spec) elif task_handler.need_to_continue(task_ex, task_spec): # Re-run existing task. cmds = [commands.RunExistingTask(task_ex, reset=False)] self._dispatch_workflow_commands(wf_ex, cmds, wf_spec)
def continue_task(task_ex): task = _build_task_from_execution(task_ex) try: task.run() except exc.MistralException as e: wf_ex = task_ex.workflow_execution msg = ( "Failed to run task [wf=%s, task=%s]: %s\n%s" % (wf_ex, task_ex.name, e, tb.format_exc()) ) LOG.error(msg) task.set_state(states.ERROR, msg) wf_handler.fail_workflow(wf_ex, msg) return if task.is_completed(): wf_handler.on_task_complete(task_ex)
def _check_workflow_completion(wf_ex, wf_ctrl, wf_spec): if states.is_paused_or_completed(wf_ex.state): return # Workflow is not completed if there are any incomplete task # executions that are not in WAITING state. If all incomplete # tasks are waiting and there are unhandled errors, then these # tasks will not reach completion. In this case, mark the # workflow complete. incomplete_tasks = wf_utils.find_incomplete_task_executions(wf_ex) if any(not states.is_waiting(t.state) for t in incomplete_tasks): return if wf_ctrl.all_errors_handled(): wf_handler.succeed_workflow( wf_ex, wf_ctrl.evaluate_workflow_final_context(), wf_spec ) else: state_info = wf_utils.construct_fail_info_message(wf_ctrl, wf_ex) wf_handler.fail_workflow(wf_ex, state_info)
def fail_task(task_ex, msg): task = _build_task_from_execution(task_ex) task.set_state(states.ERROR, msg) wf_handler.fail_workflow(task_ex.workflow_execution, msg)