/// <summary> /// Used to kick off execution of a node with a default execution context for all subjects in a serial manner. /// </summary> /// <param name="subjects">Subject to be moved through the node.</param> /// <param name="options">Execution options to apply to running this enumerable of subjects.</param> /// <returns>An aggregated NodeResult.</returns> public async Task <NodeResult> ExecuteManySeriallyAsync(IEnumerable <T> subjects, ExecutionOptions options = null) { Guard.AgainstNullArgument("subjects", subjects); var nodeTimer = new NodeTimer(); try { nodeTimer.LogStart(LogWriter, this, "ExecuteManySeriallyAsync"); _processManyMode = true; var subjectList = subjects.ToList(); Result = new NodeResult(default(T), Id, FlowId); if (subjectList.Count == 0) { return(Result); } if (options == null) { options = new ExecutionOptions(); } foreach (var subject in subjectList) { try { LogWriter.Debug("Running all subjects asynchronously in a serial manner."); NodeResult result = await ExecuteAsync(new ExecutionContext <T>(subject, options)).ConfigureAwait(false); Result.AddChildResult(result); } catch (Exception) { if (options.ThrowOnError) { throw; } if (!options.ContinueOnFailure) { break; } } } ProcessExecuteManyResults(options); return(Result); } finally { _processManyMode = false; nodeTimer.LogStop(LogWriter, this, "ExecuteAsync"); } }
/// <summary> /// Creates a new Node with local options to override global options. /// </summary> /// <param name="localOptions">Local options to override global options.</param> protected Node(ExecutionOptions localOptions) : this() { LocalOptions = localOptions; }
/// <summary> /// Aggregates the child results of a MultiNode into a summary result status. /// </summary> /// <param name="results">Results to aggregate.</param> /// <param name="options">Execution options to consider during aggregation.</param> /// <returns>Summary NodeResultStatus.</returns> public static NodeResultStatus AggregateNodeResults(this IEnumerable <NodeResult> results, ExecutionOptions options) { bool hasFailure = false; bool hasSuccess = false; bool hasSuccessWithErrors = false; foreach (var nodeResult in results) { if (!hasSuccessWithErrors && nodeResult.Status == NodeResultStatus.SucceededWithErrors) { hasSuccessWithErrors = true; } else if (!hasFailure && nodeResult.Status == NodeResultStatus.Failed) { hasFailure = true; } else if (!hasSuccess && nodeResult.Status == NodeResultStatus.Succeeded) { hasSuccess = true; } if (hasSuccess && hasFailure) { hasSuccessWithErrors = true; break; } } if (hasSuccessWithErrors) { if (hasFailure && !options.ContinueOnFailure) { return(NodeResultStatus.Failed); } return(NodeResultStatus.SucceededWithErrors); } if (hasSuccess) { return(NodeResultStatus.Succeeded); } if (hasFailure) { return(NodeResultStatus.Failed); } return(NodeResultStatus.NotRun); }