< Summary

Information
Class: TeleFlow.Framework.Updates.DefaultUpdateProcessor
Assembly: TeleFlow.Framework.Core
File(s): /_/src/TeleFlow.Framework.Core/Updates/DefaultUpdateProcessor.cs
Line coverage
97%
Covered lines: 33
Uncovered lines: 1
Coverable lines: 34
Total lines: 89
Line coverage: 97%
Branch coverage
78%
Covered branches: 11
Total branches: 14
Branch coverage: 78.5%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)50%44100%
ProcessAsync()100%44100%
EnsureRuntimeValidated(...)75%4488.88%
BuildPipeline(...)100%22100%

File(s)

/_/src/TeleFlow.Framework.Core/Updates/DefaultUpdateProcessor.cs

#LineLine coverage
 1using Microsoft.Extensions.DependencyInjection;
 2using TeleFlow.Framework.Application;
 3using TeleFlow.Framework.Dispatching;
 4using TeleFlow.Framework.Middleware;
 5
 6namespace TeleFlow.Framework.Updates;
 7
 8internal sealed class DefaultUpdateProcessor : IUpdateProcessor
 9{
 10    private readonly IServiceScopeFactory _scopeFactory;
 11    private readonly IUpdateDispatcher _dispatcher;
 12    private readonly IReadOnlyList<UpdateMiddlewareRegistration> _middleware;
 9113    private readonly object _validationLock = new();
 14    private bool _runtimeValidated;
 15
 16    public DefaultUpdateProcessor(
 17        IServiceScopeFactory scopeFactory,
 18        IUpdateDispatcher dispatcher,
 19        IEnumerable<UpdateMiddlewareRegistration> middleware)
 20    {
 9121        _scopeFactory = scopeFactory ?? throw new ArgumentNullException(nameof(scopeFactory));
 9122        _dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher));
 9123        ArgumentNullException.ThrowIfNull(middleware);
 24
 9125        _middleware = middleware.ToArray();
 9126    }
 27
 28    public async Task ProcessAsync(IUpdatePayload payload, CancellationToken cancellationToken = default)
 29    {
 9130        ArgumentNullException.ThrowIfNull(payload);
 31
 9132        var scope = _scopeFactory.CreateAsyncScope();
 9133        await using (scope.ConfigureAwait(false))
 34        {
 9135            EnsureRuntimeValidated(scope.ServiceProvider);
 36
 9037            var context = new UpdateContext(scope.ServiceProvider, payload, cancellationToken);
 9038            var currentUpdate = scope.ServiceProvider.GetService<IUpdateContextAccessorInitializer>();
 9039            var pipeline = BuildPipeline(scope.ServiceProvider, _dispatcher, _middleware);
 40
 9041            currentUpdate?.Initialize(context);
 42
 43            try
 44            {
 9045                await pipeline(context).ConfigureAwait(false);
 8446            }
 47            finally
 48            {
 9049                currentUpdate?.Clear(context);
 50            }
 8451        }
 8452    }
 53
 54    private void EnsureRuntimeValidated(IServiceProvider services)
 55    {
 9156        if (_runtimeValidated)
 57        {
 1658            return;
 59        }
 60
 7561        lock (_validationLock)
 62        {
 7563            if (_runtimeValidated)
 64            {
 065                return;
 66            }
 67
 7568            TeleFlowRuntimeValidatorRunner.Validate(services);
 7469            _runtimeValidated = true;
 7470        }
 7471    }
 72
 73    private static UpdateDelegate BuildPipeline(
 74        IServiceProvider services,
 75        IUpdateDispatcher dispatcher,
 76        IReadOnlyList<UpdateMiddlewareRegistration> middleware)
 77    {
 17778        UpdateDelegate pipeline = context => dispatcher.DispatchAsync(context, context.CancellationToken);
 79
 30080        for (var index = middleware.Count - 1; index >= 0; index--)
 81        {
 6082            var current = middleware[index].Resolve(services);
 6083            var next = pipeline;
 12084            pipeline = context => current.InvokeAsync(context, next);
 85        }
 86
 9087        return pipeline;
 88    }
 89}