< Summary

Information
Class: Elsa.Workflows.Runtime.Services.InterruptedRecoveryScanner
Assembly: Elsa.Workflows.Runtime
File(s): /home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Workflows.Runtime/Services/InterruptedRecoveryScanner.cs
Line coverage
100%
Covered lines: 35
Uncovered lines: 0
Coverable lines: 35
Total lines: 78
Line coverage: 100%
Branch coverage
92%
Covered branches: 13
Total branches: 14
Branch coverage: 92.8%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
ScanAndRequeueAsync()92.85%1414100%

File(s)

/home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Workflows.Runtime/Services/InterruptedRecoveryScanner.cs

#LineLine coverage
 1using Elsa.Common;
 2using Elsa.Common.Multitenancy;
 3using Elsa.Workflows.Management;
 4using Elsa.Workflows.Management.Filters;
 5using Elsa.Workflows.Runtime.Options;
 6using Microsoft.Extensions.Logging;
 7using Microsoft.Extensions.Options;
 8
 9namespace Elsa.Workflows.Runtime.Services;
 10
 11/// <summary>
 12/// Default implementation of <see cref="IInterruptedRecoveryScanner"/>.
 13/// </summary>
 14public sealed class InterruptedRecoveryScanner : IInterruptedRecoveryScanner
 15{
 16    private readonly IWorkflowRestarter _restarter;
 17    private readonly IWorkflowInstanceStore _instanceStore;
 18    private readonly IOptions<RuntimeOptions> _runtimeOptions;
 19    private readonly ILogger<InterruptedRecoveryScanner> _logger;
 20    private readonly ITenantService? _tenantService;
 21    private readonly ITenantAccessor? _tenantAccessor;
 22
 10823    public InterruptedRecoveryScanner(
 10824        IWorkflowRestarter restarter,
 10825        IWorkflowInstanceStore instanceStore,
 10826        IOptions<RuntimeOptions> runtimeOptions,
 10827        ILogger<InterruptedRecoveryScanner> logger,
 10828        ITenantService? tenantService = null,
 10829        ITenantAccessor? tenantAccessor = null)
 30    {
 10831        _restarter = restarter;
 10832        _instanceStore = instanceStore;
 10833        _runtimeOptions = runtimeOptions;
 10834        _logger = logger;
 10835        _tenantService = tenantService;
 10836        _tenantAccessor = tenantAccessor;
 10837    }
 38
 39    /// <inheritdoc />
 40    public async ValueTask<int> ScanAndRequeueAsync(CancellationToken cancellationToken)
 41    {
 10842        var filter = new WorkflowInstanceFilter { WorkflowSubStatus = WorkflowSubStatus.Interrupted };
 10843        var batchSize = _runtimeOptions.Value.RestartInterruptedWorkflowsBatchSize;
 10844        var instances = _instanceStore.EnumerateSummariesAsync(filter, batchSize, cancellationToken);
 10845        var requeued = 0;
 46
 10847        _logger.LogInformation("Scanning for workflows interrupted by graceful drain.");
 48
 47049        await foreach (var summary in instances.WithCancellation(cancellationToken))
 50        {
 51            try
 52            {
 12753                var tenantId = summary.TenantId ?? string.Empty;
 54
 12755                if (_tenantService is not null && _tenantAccessor is not null && !string.IsNullOrWhiteSpace(tenantId) &&
 56                {
 157                    var tenant = await _tenantService.FindAsync(tenantId, cancellationToken) ?? new Tenant { Id = tenant
 58
 159                    using (_tenantAccessor.PushContext(tenant))
 160                        await _restarter.RestartWorkflowAsync(summary.Id, cancellationToken);
 61                }
 62                else
 63                {
 12664                    await _restarter.RestartWorkflowAsync(summary.Id, cancellationToken);
 65                }
 66
 12667                requeued++;
 12668            }
 169            catch (Exception ex) when (!ex.IsFatal())
 70            {
 171                _logger.LogError(ex, "Failed to requeue interrupted workflow {WorkflowInstanceId}; will be retried by th
 172            }
 12773        }
 74
 10875        _logger.LogInformation("Interrupted-workflow scan complete; requeued {Count} instance(s).", requeued);
 10876        return requeued;
 10877    }
 78}