private void Handle(TaskFailed message) { HandleChildTaskFailed(message); }
/// <summary> /// Handle child task failed event. /// Warning: TODO: when we have a FailedActive task, /// next TaskFailedEvent will set its status to Failed and handle the failure. /// TODO: handle a case when the transition is 'cancelling' but the task fails or completes /// before nginn cancels it /// </summary> /// <param name="tfe"></param> private void HandleChildTaskFailed(TaskFailed tfe) { lock (this) { if (tfe.ParentTaskInstanceId != this.InstanceId) throw new TaskRuntimeException("Parent task correlation id is incorrect").SetInstanceId(InstanceId); TransitionInfo ti = GetTransitionInfo(tfe.FromTaskInstanceId); if (ti == null) throw new TaskInstanceNotFoundException(tfe.FromTaskInstanceId); log.Info("Child task {0} failed: {1}", tfe.FromTaskInstanceId, tfe.ErrorInfo); if (ti.Status == TransitionStatus.Failed) { return; } else if (ti.IsTransitionActive) //also if is FailedActive { if (ti.Status == TransitionStatus.Enabling) ti.Status = TransitionStatus.Enabled; ConsumeTaskInputTokens(tfe.FromTaskInstanceId); List<FlowDef> handlers = new List<FlowDef>(MyTask.GetTask(ti.TaskId).GetFlowsForPortOut(TaskOutPortType.Error)); if (handlers.Count > 0) { ti.Status = TransitionStatus.Failed; log.Info("Continuing with {0} error handlers", ti.TaskId); ProduceTaskOutputTokens(ti.InstanceId); } else { bool isErrorTask = tfe.IsExpected; TaskDef tsk = MyTask.GetTask(ti.TaskId); //if the task is already failed or it has error handlers set up if (isErrorTask || ti.Status == TransitionStatus.FailedActive || MyTask.GetFlowsForPortOut(TaskOutPortType.Error).FirstOrDefault() != null) { ti.Status = TransitionStatus.Failed; log.Info("Failing current task: {0}!", ti.TaskId, InstanceId); ForceFail(tfe.ErrorInfo); //TODO?? maybe FailInternal()... return; } else { log.Info("No error handlers for task {0} and not bubbling up.", ti.TaskId); ti.Status = TransitionStatus.FailedActive; //RG: v2 TODO //Context.MessageBus.Notify(new ChildTaskFailedNotification(ti.InstanceId, InstanceId, string.Format("Unexpected task error ({0}/{1}): {2}", ProcessDefinition.DefinitionId, ti.TaskId, tfe.ErrorInfo))); } } } else { log.Warn("Child task {0} ({1}) failed, but current transition status is {2}. Ignoring the notification - status inconsistent", tfe.FromTaskInstanceId, ti.TaskId, ti.Status); return; } //throw new Exception("Invalid task status!"); } }
private void Handle(TaskFailed message) { RequireActivation(true); if (message.ParentTaskInstanceId != this.InstanceId) throw new Exception(); TransitionInfo ti = GetTransition(message.FromTaskInstanceId); if (ti == null) throw new Exception(); lock (this) { log.Info("Child task {0} has failed: {1}", ti.InstanceId, message.ErrorInfo); if (ti.Status == TransitionStatus.Failed) return; if (!ti.IsTransitionActive) { log.Warn("Transition {0} ({1}) is not active: {2}", ti.InstanceId, ti.TaskId, ti.Status); return; } if (message.IsExpected) { ti.Status = TransitionStatus.Failed; if (!AllowChildTaskFailures) { DefaultHandleTaskFailure(message.ErrorInfo, true); return; } } else { ti.Status = TransitionStatus.FailedActive; } OnTransitionStatusChanged(ti.InstanceId); return; } }