< Summary

Information
Class: NexMediator.Core.Pipeline.PipelineBehaviorExecutor<T1, T2>
Assembly: NexMediator.Pipeline
File(s): /home/runner/work/NexMediator/NexMediator/src/NexMediator.Pipeline/PipelineBehaviorExecutor.cs
Line coverage
100%
Covered lines: 39
Uncovered lines: 0
Coverable lines: 39
Total lines: 124
Line coverage: 100%
Branch coverage
100%
Covered branches: 10
Total branches: 10
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%66100%
Execute()100%44100%
ExecutePipeline(...)100%11100%

File(s)

/home/runner/work/NexMediator/NexMediator/src/NexMediator.Pipeline/PipelineBehaviorExecutor.cs

#LineLine coverage
 1using Microsoft.Extensions.DependencyInjection;
 2using NexMediator.Abstractions.Interfaces;
 3
 4namespace NexMediator.Core.Pipeline;
 5
 6/// <summary>
 7/// Internal executor that manages the complete request processing pipeline
 8/// </summary>
 9/// <typeparam name="TRequest">Request type</typeparam>
 10/// <typeparam name="TResponse">Response type</typeparam>
 11/// <remarks>
 12/// Pipeline sequence:
 13/// 1. Pre-processor execution
 14/// 2. Behavior pipeline execution
 15/// 3. Handler invocation
 16/// 4. Post-processor execution
 17///
 18/// Features:
 19/// - Sequential behavior execution
 20/// - Resource management
 21/// - Error propagation
 22/// - Cancellation support
 23/// </remarks>
 24public class PipelineBehaviorExecutor<TRequest, TResponse>
 25    where TRequest : INexRequest<TResponse>
 26{
 27    private readonly INexRequestHandler<TRequest, TResponse> _handler;
 28    private readonly IEnumerable<INexPipelineBehavior<TRequest, TResponse>> _behaviors;
 29    private readonly IServiceProvider _serviceProvider;
 30
 31    /// <summary>
 32    /// Initializes a new executor instance
 33    /// </summary>
 34    /// <param name="serviceProvider">DI container access</param>
 35    /// <param name="handler">Core request handler</param>
 36    /// <param name="behaviors">Ordered behavior pipeline</param>
 37    /// <remarks>
 38    /// Dependencies:
 39    /// - Service provider for processors
 40    /// - Request handler instance
 41    /// - Configured behaviors
 42    /// </remarks>
 43    /// <exception cref="ArgumentNullException">When any dependency is null</exception>
 1444    public PipelineBehaviorExecutor(
 1445        IServiceProvider serviceProvider,
 1446        INexRequestHandler<TRequest, TResponse> handler,
 1447        IEnumerable<INexPipelineBehavior<TRequest, TResponse>> behaviors)
 1448    {
 1449        _serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
 1250        _handler = handler ?? throw new ArgumentNullException(nameof(handler));
 1051        _behaviors = behaviors ?? Enumerable.Empty<INexPipelineBehavior<TRequest, TResponse>>();
 1052    }
 53
 54    /// <summary>
 55    /// Executes the complete pipeline for a request
 56    /// </summary>
 57    /// <param name="request">Request to process</param>
 58    /// <param name="cancellationToken">Optional cancellation token</param>
 59    /// <returns>Response after pipeline execution</returns>
 60    /// <remarks>
 61    /// Execution flow:
 62    /// 1. Check cancellation state
 63    /// 2. Execute pre-processors
 64    /// 3. Run main pipeline
 65    /// 4. Execute post-processors
 66    /// 5. Return final result
 67    /// </remarks>
 68    /// <exception cref="OperationCanceledException">When operation is cancelled</exception>
 69    public async Task<TResponse> Execute(TRequest request, CancellationToken cancellationToken)
 1070    {
 71        // Check cancellation before starting pipeline
 1072        cancellationToken.ThrowIfCancellationRequested();
 73
 74        // Execute pre-processors
 975        var preProcessors = _serviceProvider.GetServices<INexRequestPreProcessor<TRequest>>();
 3076        foreach (var processor in preProcessors)
 277        {
 278            await processor.Process(request, cancellationToken);
 179        }
 80
 81        // Execute the main pipeline
 882        var response = await ExecutePipeline(request, cancellationToken);
 83
 84        // Execute post-processors
 685        var postProcessors = _serviceProvider.GetServices<INexRequestPostProcessor<TRequest, TResponse>>();
 2386        foreach (var processor in postProcessors)
 387        {
 388            await processor.Process(request, response, cancellationToken);
 289        }
 90
 591        return response;
 592    }
 93
 94    /// <summary>
 95    /// Executes the core behavior pipeline
 96    /// </summary>
 97    /// <param name="request">Request to process</param>
 98    /// <param name="cancellationToken">Optional cancellation token</param>
 99    /// <returns>Pipeline execution result</returns>
 100    /// <remarks>
 101    /// Implementation:
 102    /// - Builds nested delegates
 103    /// - Executes behaviors in order
 104    /// - Handles cancellation
 105    /// - Manages handler invocation
 106    /// </remarks>
 107    private Task<TResponse> ExecutePipeline(TRequest request, CancellationToken cancellationToken)
 8108    {
 8109        var pipeline = _behaviors.Reverse()
 8110            .Aggregate(
 8111                (RequestHandlerDelegate<TResponse>)(async () =>
 7112                {
 7113                    cancellationToken.ThrowIfCancellationRequested();
 7114                    return await _handler.Handle(request, cancellationToken);
 7115                }),
 14116                (next, pipeline) => async () =>
 6117                {
 6118                    cancellationToken.ThrowIfCancellationRequested();
 6119                    return await pipeline.Handle(request, next, cancellationToken);
 18120                });
 121
 8122        return pipeline();
 8123    }
 124}