def _continue_workflow(self, wf_ex, task_ex=None, reset=True): wf_handler.set_execution_state(wf_ex, states.RUNNING) wf_ctrl = wf_base.WorkflowController.get_controller(wf_ex) # Calculate commands to process next. cmds = wf_ctrl.continue_workflow(task_ex=task_ex, reset=reset) # When resuming a workflow we need to ignore all 'pause' # commands because workflow controller takes tasks that # completed within the period when the workflow was pause. cmds = filter( lambda c: not isinstance(c, commands.PauseWorkflow), cmds ) # Since there's no explicit task causing the operation # we need to mark all not processed tasks as processed # because workflow controller takes only completed tasks # with flag 'processed' equal to False. for t_ex in wf_ex.task_executions: if states.is_completed(t_ex.state) and not t_ex.processed: t_ex.processed = True self._dispatch_workflow_commands(wf_ex, cmds) if not cmds: if not wf_utils.find_incomplete_task_executions(wf_ex): wf_handler.succeed_workflow( wf_ex, wf_ctrl.evaluate_workflow_final_context() ) return wf_ex.get_clone()
def _continue_workflow(self, wf_ex, task_ex=None, reset=True, env=None): wf_ex = wf_service.update_workflow_execution_env(wf_ex, env) wf_handler.set_execution_state(wf_ex, states.RUNNING, set_upstream=True) wf_ctrl = wf_base.WorkflowController.get_controller(wf_ex) # Calculate commands to process next. cmds = wf_ctrl.continue_workflow(task_ex=task_ex, reset=reset, env=env) # When resuming a workflow we need to ignore all 'pause' # commands because workflow controller takes tasks that # completed within the period when the workflow was pause. cmds = list( filter(lambda c: not isinstance(c, commands.PauseWorkflow), cmds)) # Since there's no explicit task causing the operation # we need to mark all not processed tasks as processed # because workflow controller takes only completed tasks # with flag 'processed' equal to False. for t_ex in wf_ex.task_executions: if states.is_completed(t_ex.state) and not t_ex.processed: t_ex.processed = True self._dispatch_workflow_commands(wf_ex, cmds) if not cmds: if not wf_utils.find_incomplete_task_executions(wf_ex): wf_handler.succeed_workflow( wf_ex, wf_ctrl.evaluate_workflow_final_context()) return wf_ex.get_clone()
def resume_workflow(self, execution_id): try: with db_api.transaction(): # Must be before loading the object itself (see method doc). self._lock_workflow_execution(execution_id) wf_ex = db_api.get_workflow_execution(execution_id) if wf_ex.state != states.PAUSED: return wf_handler.set_execution_state(wf_ex, states.RUNNING) wf_ctrl = wf_base.WorkflowController.get_controller(wf_ex) # Calculate commands to process next. cmds = wf_ctrl.continue_workflow() # When resuming a workflow we need to ignore all 'pause' # commands because workflow controller takes tasks that # completed within the period when the workflow was pause. cmds = filter( lambda c: not isinstance(c, commands.PauseWorkflow), cmds ) # Since there's no explicit task causing the operation # we need to mark all not processed tasks as processed # because workflow controller takes only completed tasks # with flag 'processed' equal to False. for t_ex in wf_ex.task_executions: if states.is_completed(t_ex.state) and not t_ex.processed: t_ex.processed = True self._dispatch_workflow_commands(wf_ex, cmds) if not cmds: if not wf_utils.find_incomplete_tasks(wf_ex): wf_handler.succeed_workflow( wf_ex, wf_ctrl.evaluate_workflow_final_context() ) return wf_ex except Exception as e: LOG.error( "Failed to resume execution id=%s: %s\n%s", execution_id, e, traceback.format_exc() ) self._fail_workflow(execution_id, e) raise e
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 _continue_workflow(self, wf_ex, task_ex=None, reset=True, env=None): wf_ex = wf_service.update_workflow_execution_env(wf_ex, env) wf_handler.set_execution_state( wf_ex, states.RUNNING, set_upstream=True ) wf_ctrl = wf_base.get_controller(wf_ex) # TODO(rakhmerov): Add YAQL error handling. # Calculate commands to process next. cmds = wf_ctrl.continue_workflow(task_ex=task_ex, reset=reset, env=env) # When resuming a workflow we need to ignore all 'pause' # commands because workflow controller takes tasks that # completed within the period when the workflow was paused. cmds = list( filter( lambda c: not isinstance(c, commands.PauseWorkflow), cmds ) ) # Since there's no explicit task causing the operation # we need to mark all not processed tasks as processed # because workflow controller takes only completed tasks # with flag 'processed' equal to False. for t_ex in wf_ex.task_executions: if states.is_completed(t_ex.state) and not t_ex.processed: t_ex.processed = True wf_spec = spec_parser.get_workflow_spec(wf_ex.spec) self._dispatch_workflow_commands(wf_ex, cmds, wf_spec) if not cmds: if not wf_utils.find_incomplete_task_executions(wf_ex): wf_handler.succeed_workflow( wf_ex, wf_ctrl.evaluate_workflow_final_context(), wf_spec ) return wf_ex.get_clone()
def resume_workflow(self, execution_id): try: with db_api.transaction(): # Must be before loading the object itself (see method doc). self._lock_workflow_execution(execution_id) wf_ex = db_api.get_workflow_execution(execution_id) if wf_ex.state != states.PAUSED: return wf_ex wf_handler.set_execution_state(wf_ex, states.RUNNING) wf_ctrl = wf_base.WorkflowController.get_controller(wf_ex) # Calculate commands to process next. cmds = wf_ctrl.continue_workflow() # When resuming a workflow we need to ignore all 'pause' # commands because workflow controller takes tasks that # completed within the period when the workflow was pause. cmds = filter( lambda c: not isinstance(c, commands.PauseWorkflow), cmds) # Since there's no explicit task causing the operation # we need to mark all not processed tasks as processed # because workflow controller takes only completed tasks # with flag 'processed' equal to False. for t_ex in wf_ex.task_executions: if states.is_completed(t_ex.state) and not t_ex.processed: t_ex.processed = True self._dispatch_workflow_commands(wf_ex, cmds) if not cmds: if not wf_utils.find_incomplete_tasks(wf_ex): wf_handler.succeed_workflow( wf_ex, wf_ctrl.evaluate_workflow_final_context()) return wf_ex except Exception as e: LOG.error("Failed to resume execution id=%s: %s\n%s", execution_id, e, traceback.format_exc()) self._fail_workflow(execution_id, e) raise e
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 _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 _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, 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)