< Summary

Information
Class: Elsa.Common.ShellHandlers.MediatorBackgroundProcessingCoordinator
Assembly: Elsa.Common
File(s): /home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Common/ShellHandlers/MediatorBackgroundProcessingCoordinator.cs
Line coverage
86%
Covered lines: 39
Uncovered lines: 6
Coverable lines: 45
Total lines: 91
Line coverage: 86.6%
Branch coverage
90%
Covered branches: 9
Total branches: 10
Branch coverage: 90%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
StartAsync()100%22100%
StopAsync()87.5%9875%
DisposeAsync()100%11100%

File(s)

/home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Common/ShellHandlers/MediatorBackgroundProcessingCoordinator.cs

#LineLine coverage
 1using Elsa.Mediator.Services;
 2using Microsoft.Extensions.Logging;
 3
 4namespace Elsa.Common.ShellHandlers;
 5
 26public sealed class MediatorBackgroundProcessingCoordinator(
 27    BackgroundCommandProcessor commandProcessor,
 28    BackgroundNotificationProcessor notificationProcessor,
 29    BackgroundJobProcessor jobProcessor,
 210    ILogger<MediatorBackgroundProcessingCoordinator> logger) : IAsyncDisposable
 11{
 212    private readonly SemaphoreSlim _lock = new(1, 1);
 13    private CancellationTokenSource? _cancellationTokenSource;
 14    private Task? _processingTask;
 15    private int _referenceCount;
 16
 17    public async Task StartAsync(CancellationToken cancellationToken = default)
 18    {
 319        await _lock.WaitAsync(cancellationToken);
 20        try
 21        {
 322            if (_referenceCount++ > 0)
 123                return;
 24
 225            _cancellationTokenSource = new();
 226            _processingTask = Task.WhenAll(
 227                commandProcessor.ExecuteAsync(_cancellationTokenSource.Token),
 228                notificationProcessor.ExecuteAsync(_cancellationTokenSource.Token),
 229                jobProcessor.ExecuteAsync(_cancellationTokenSource.Token));
 230        }
 31        finally
 32        {
 333            _lock.Release();
 34        }
 335    }
 36
 37    public async Task StopAsync(CancellationToken cancellationToken = default)
 38    {
 39        Task? processingTask;
 40        CancellationTokenSource? cancellationTokenSource;
 41
 542        await _lock.WaitAsync(cancellationToken);
 43        try
 44        {
 545            if (_referenceCount == 0)
 046                return;
 47
 548            if (--_referenceCount > 0)
 149                return;
 50
 451            processingTask = _processingTask;
 452            cancellationTokenSource = _cancellationTokenSource;
 453            _processingTask = null;
 454            _cancellationTokenSource = null;
 455        }
 56        finally
 57        {
 558            _lock.Release();
 59        }
 60
 461        if (cancellationTokenSource is null)
 262            return;
 63
 264        await cancellationTokenSource.CancelAsync();
 65
 266        if (processingTask is not null)
 67        {
 68            try
 69            {
 270                await processingTask.WaitAsync(cancellationToken);
 271            }
 072            catch (OperationCanceledException) when (cancellationTokenSource.IsCancellationRequested)
 73            {
 074            }
 075            catch (Exception e)
 76            {
 077                logger.LogError(e, "An error occurred while stopping mediator background processing");
 078                throw;
 79            }
 80        }
 81
 282        cancellationTokenSource.Dispose();
 583    }
 84
 85    public async ValueTask DisposeAsync()
 86    {
 287        _referenceCount = 1;
 288        await StopAsync(CancellationToken.None);
 289        _lock.Dispose();
 290    }
 91}