Ejemplo n.º 1
0
        /// <summary>
        /// Used to kick off execution of a node with a default execution context for all subjects using Async WhenAll semantics internally .
        /// </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> ExecuteManyAsync(IEnumerable <T> subjects, ExecutionOptions options = null)
        {
            Guard.AgainstNullArgument("subjects", subjects);

            var nodeTimer = new NodeTimer();

            try
            {
                nodeTimer.LogStart(LogWriter, this, "ExecuteManyAsync");
                _processManyMode = true;
                Result           = new NodeResult(default(T), Id, FlowId);

                var subjectList = subjects.ToList();

                if (subjectList.Count == 0)
                {
                    return(Result);
                }

                if (options == null)
                {
                    options = new ExecutionOptions();
                }

                LogWriter.Debug("Running all subjects asynchronously.");

                Task aggregateTask = null;
                try
                {
                    var resultsQueue = new ConcurrentQueue <NodeResult>();
                    aggregateTask = subjectList.ForEachAsync(options.DegreeOfParallelism,
                                                             async x => resultsQueue.Enqueue(await ExecuteAsync(new ExecutionContext <T>(x, options))));

                    await aggregateTask;

                    Result.AddChildResults(resultsQueue);
                }
                catch
                {
                    if (options.ThrowOnError)
                    {
                        if (aggregateTask != null && aggregateTask.Exception != null)
                        {
                            throw aggregateTask.Exception;
                        }

                        throw;
                    }
                }

                ProcessExecuteManyResults(options);
                return(Result);
            }
            finally
            {
                _processManyMode = false;
                nodeTimer.LogStop(LogWriter, this, "ExecuteAsync");
            }
        }
Ejemplo n.º 2
0
        /// <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");
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Used to kick off execution of a node with a specified execution context.
        /// </summary>
        /// <param name="sourceContext">ExecutionContext that includes a subject to be moved through the node.</param>
        /// <returns>A NodeResult</returns>
        public async Task <NodeResult> ExecuteAsync(IExecutionContext <T> sourceContext)
        {
            Guard.AgainstNullArgument("context", sourceContext);
            Guard.AgainstNullArgumentProperty("context", "Subject", sourceContext.Subject);

            var nodeTimer = new NodeTimer();

            try
            {
                nodeTimer.LogStart(LogWriter, this, "ExecuteAsync");

                if (Status != NodeRunStatus.NotRun)
                {
                    LogWriter.Debug("Status does not equal 'NotRun', resetting the node before execution");
                    Reset();
                }

                var subject = sourceContext.Subject;
                var result  = new NodeResult(subject, Id, FlowId);
                if (!_processManyMode)
                {
                    Result = result;
                }

                IExecutionContext <T> context = PrepareExecutionContext(sourceContext, result);

                OnBeforeExecute(context);

                if (!context.CancelProcessing)
                {
                    var effectiveOptions = GetEffectiveOptions(context.GlobalOptions);

                    if (!await ShouldExecuteInternalAsync(context).ConfigureAwait(false))
                    {
                        LogWriter.Info("ShouldExecute returned false, skipping execution");
                        return(result);
                    }

                    Status = NodeRunStatus.Running;
                    LogWriter.Debug("Executing the node");

                    try
                    {
                        result.Status = await PerformExecuteAsync(context).ConfigureAwait(false);

                        //Reset the subject in case it was changed.
                        result.Subject = context.Subject;
                        Status         = NodeRunStatus.Completed;
                        LogWriter.Info("Node completed execution, status is {0}", result.Status);
                    }
                    catch (Exception ex)
                    {
                        LogWriter.Error("Node erred during execution, status is Failed", ex);
                        Status           = NodeRunStatus.Faulted;
                        result.Subject   = context.Subject;
                        result.Status    = NodeResultStatus.Failed;
                        result.Exception = ex;

                        if (effectiveOptions.ThrowOnError)
                        {
                            throw;
                        }
                    }

                    OnAfterExecute(context);
                }

                sourceContext.CancelProcessing = context.CancelProcessing;

                return(result);
            }
            finally
            {
                nodeTimer.LogStop(LogWriter, this, "ExecuteAsync");
            }
        }