def process_workflow_event(cls, workflow_state, wf_ex_event): # Append additional workflow context to the event. event_name = cls.add_context_to_workflow_event(workflow_state, wf_ex_event) # Check if event is valid. if event_name not in events.WORKFLOW_EXECUTION_EVENTS: raise exc.InvalidEvent(event_name) # Capture current workflow status. current_workflow_status = workflow_state.status new_workflow_status = current_workflow_status # Check if the current workflow status can be transitioned. if current_workflow_status not in WORKFLOW_STATE_MACHINE_DATA: raise exc.InvalidWorkflowStatusTransition(current_workflow_status, event_name) # If the current workflow status can be transitioned and there is no match on the # event, then there is not status transition. if event_name not in WORKFLOW_STATE_MACHINE_DATA[current_workflow_status]: return new_workflow_status = WORKFLOW_STATE_MACHINE_DATA[current_workflow_status][event_name] # Assign new workflow status if there is change. if current_workflow_status != new_workflow_status: workflow_state.status = new_workflow_status
def request_workflow_status(self, status): # Record current workflow status. current_status = self.get_workflow_status() # Create an event for the request. wf_ex_event = events.WorkflowExecutionEvent(status) # Push the event to all the active tasks. The event may trigger status changes to the task. for task_state in self.workflow_state.get_tasks_by_status(statuses.ACTIVE_STATUSES): machines.TaskStateMachine.process_event(self.workflow_state, task_state, wf_ex_event) # Process the workflow status change event. machines.WorkflowStateMachine.process_event(self.workflow_state, wf_ex_event) # Get workflow status after event is processed. updated_status = self.get_workflow_status() # Ignore if workflow hasn't changed from paused to pausing. if (status == statuses.PAUSED and current_status == statuses.PAUSING and updated_status == statuses.PAUSING): return # Ignore if workflow hasn't changed from canceled to canceling. if (status == statuses.CANCELED and current_status == statuses.CANCELING and updated_status == statuses.CANCELING): return # Otherwise, if status has not changed as expected, then raise exception. if status != current_status and current_status == updated_status: raise exc.InvalidWorkflowStatusTransition(current_status, wf_ex_event.name)
def process_task_event(cls, workflow_state, tk_ex_event): # Append additional workflow context to the event. event_name = cls.add_context_to_task_event(workflow_state, tk_ex_event) # Check if event is valid. if event_name not in events.TASK_EXECUTION_EVENTS: raise exc.InvalidEvent(event_name) # Capture current workflow status. current_workflow_status = workflow_state.status new_workflow_status = current_workflow_status # Check if the current workflow status can be transitioned. if current_workflow_status not in WORKFLOW_STATE_MACHINE_DATA: raise exc.InvalidWorkflowStatusTransition(current_workflow_status, event_name) # If the current workflow status can be transitioned and there is no match on the # event, then there is not status transition. if event_name not in WORKFLOW_STATE_MACHINE_DATA[ current_workflow_status]: return new_workflow_status = WORKFLOW_STATE_MACHINE_DATA[ current_workflow_status][event_name] # Assign new workflow status if there is change. if current_workflow_status != new_workflow_status: workflow_state.status = new_workflow_status # If the final workflow status here is completed, then ensure there is no unreachable # barrier task(s). A barrier task is unreachable if the workflow is completed but then one # or more criteria for the task is satisified. In this case, log the task and fail the # workflow to notify that the execution is incomplete but unable to proceed. if workflow_state.status in statuses.COMPLETED_STATUSES: unreachable_barriers = workflow_state.get_unreachable_barriers() # If there are unreachable barrier tasks, then change workflow status to failed # and write an error log for each case. if unreachable_barriers: workflow_state.status = statuses.FAILED for entry in unreachable_barriers: e = exc.UnreachableJoinError(entry["id"], entry["route"]) workflow_state.conductor.log_error(e, task_id=entry["id"], route=entry["route"])
def request_workflow_status(self, status): # Record current workflow status. current_status = self.get_workflow_status() # Create an event for the request. wf_ex_event = events.WorkflowExecutionEvent(status) # Push the event to all the active tasks. The event may trigger status changes to the task. for task_state in self.workflow_state.get_tasks_by_status( statuses.ACTIVE_STATUSES): machines.TaskStateMachine.process_event(self.workflow_state, task_state, wf_ex_event) # Process the workflow status change event. machines.WorkflowStateMachine.process_event(self.workflow_state, wf_ex_event) # Get workflow status after event is processed. updated_status = self.get_workflow_status() # If status has not changed as expected, then raise exception. if status != current_status and current_status == updated_status: raise exc.InvalidWorkflowStatusTransition(current_status, wf_ex_event.name)