< 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: 39
Uncovered lines: 0
Coverable lines: 39
Total lines: 82
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
 11223    public InterruptedRecoveryScanner(
 11224        IWorkflowRestarter restarter,
 11225        IWorkflowInstanceStore instanceStore,
 11226        IOptions<RuntimeOptions> runtimeOptions,
 11227        ILogger<InterruptedRecoveryScanner> logger,
 11228        ITenantService? tenantService = null,
 11229        ITenantAccessor? tenantAccessor = null)
 30    {
 11231        _restarter = restarter;
 11232        _instanceStore = instanceStore;
 11233        _runtimeOptions = runtimeOptions;
 11234        _logger = logger;
 11235        _tenantService = tenantService;
 11236        _tenantAccessor = tenantAccessor;
 11237    }
 38
 39    /// <inheritdoc />
 40    public async ValueTask<int> ScanAndRequeueAsync(CancellationToken cancellationToken)
 41    {
 11342        var filter = new WorkflowInstanceFilter
 11343        {
 11344            WorkflowSubStatus = WorkflowSubStatus.Interrupted,
 11345            WorkflowStatus = WorkflowStatus.Running,
 11346        };
 11347        var batchSize = _runtimeOptions.Value.RestartInterruptedWorkflowsBatchSize;
 11348        var instances = _instanceStore.EnumerateSummariesAsync(filter, batchSize, cancellationToken);
 11349        var requeued = 0;
 50
 11351        _logger.LogInformation("Scanning for workflows interrupted by graceful drain.");
 52
 48653        await foreach (var summary in instances.WithCancellation(cancellationToken))
 54        {
 55            try
 56            {
 13057                var tenantId = summary.TenantId ?? string.Empty;
 58
 13059                if (_tenantService is not null && _tenantAccessor is not null && !string.IsNullOrWhiteSpace(tenantId) &&
 60                {
 161                    var tenant = await _tenantService.FindAsync(tenantId, cancellationToken) ?? new Tenant { Id = tenant
 62
 163                    using (_tenantAccessor.PushContext(tenant))
 164                        await _restarter.RestartWorkflowAsync(summary.Id, cancellationToken);
 65                }
 66                else
 67                {
 12968                    await _restarter.RestartWorkflowAsync(summary.Id, cancellationToken);
 69                }
 70
 12971                requeued++;
 12972            }
 173            catch (Exception ex) when (!ex.IsFatal())
 74            {
 175                _logger.LogError(ex, "Failed to requeue interrupted workflow {WorkflowInstanceId}; will be retried by th
 176            }
 13077        }
 78
 11379        _logger.LogInformation("Interrupted-workflow scan complete; requeued {Count} instance(s).", requeued);
 11380        return requeued;
 11381    }
 82}