< Summary

Information
Class: Elsa.Alterations.Services.DefaultAlterationRunner
Assembly: Elsa.Alterations
File(s): /home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Alterations/Services/DefaultAlterationRunner.cs
Line coverage
90%
Covered lines: 36
Uncovered lines: 4
Coverable lines: 40
Total lines: 100
Line coverage: 90%
Branch coverage
62%
Covered branches: 5
Total branches: 8
Branch coverage: 62.5%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
RunAsync()75%44100%
RunAsync()50%4484%

File(s)

/home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Alterations/Services/DefaultAlterationRunner.cs

#LineLine coverage
 1using Elsa.Alterations.Core.Contracts;
 2using Elsa.Alterations.Core.Models;
 3using Elsa.Alterations.Core.Results;
 4using Elsa.Alterations.Middleware.Workflows;
 5using Elsa.Common;
 6using Elsa.Workflows;
 7using Elsa.Workflows.CommitStates;
 8using Elsa.Workflows.Management;
 9using Elsa.Workflows.Pipelines.WorkflowExecution;
 10using Elsa.Workflows.Runtime;
 11using Microsoft.Extensions.Logging;
 12
 13namespace Elsa.Alterations.Services;
 14
 15/// <inheritdoc />
 616public class DefaultAlterationRunner(
 617    IWorkflowRuntime workflowRuntime,
 618    IWorkflowExecutionPipeline workflowExecutionPipeline,
 619    IWorkflowDefinitionService workflowDefinitionService,
 620    IWorkflowStateExtractor workflowStateExtractor,
 621    ICommitStateHandler commitStateHandler,
 622    ISystemClock systemClock,
 623    IServiceProvider serviceProvider)
 24    : IAlterationRunner
 25{
 26    /// <inheritdoc />
 27    public async Task<ICollection<RunAlterationsResult>> RunAsync(IEnumerable<string> workflowInstanceIds, IEnumerable<I
 28    {
 329        var results = new List<RunAlterationsResult>();
 330        var alterationList = alterations as ICollection<IAlteration> ?? alterations.ToList();
 31
 1232        foreach (var workflowInstanceId in workflowInstanceIds)
 33        {
 334            var result = await RunAsync(workflowInstanceId, alterationList, cancellationToken);
 335            results.Add(result);
 36        }
 37
 338        return results;
 339    }
 40
 41    /// <inheritdoc />
 42    public async Task<RunAlterationsResult> RunAsync(string workflowInstanceId, IEnumerable<IAlteration> alterations, Ca
 43    {
 344        var log = new AlterationLog(systemClock);
 345        var result = new RunAlterationsResult(workflowInstanceId, log);
 346        var workflowClient = await workflowRuntime.CreateClientAsync(workflowInstanceId, cancellationToken: cancellation
 47
 48        // Load workflow instance.
 349        var workflowState = await workflowClient.ExportStateAsync(cancellationToken);
 50
 351        if (workflowState == null)
 52        {
 053            log.Add($"Workflow instance with ID '{workflowInstanceId}' not found.", LogLevel.Error);
 054            return result;
 55        }
 56
 57        // Load workflow definition.
 358        var workflowGraph = await workflowDefinitionService.FindWorkflowGraphAsync(workflowState.DefinitionVersionId, ca
 59
 360        if (workflowGraph == null)
 61        {
 062            log.Add($"Workflow definition with ID '{workflowState.DefinitionVersionId}' not found.", LogLevel.Error);
 063            return result;
 64        }
 65
 66        // Create workflow execution context.
 367        var workflowExecutionContext = await WorkflowExecutionContext.CreateAsync(serviceProvider, workflowGraph, workfl
 368        workflowExecutionContext.TransientProperties.Add(RunAlterationsMiddleware.AlterationsPropertyKey, alterations);
 369        workflowExecutionContext.TransientProperties.Add(RunAlterationsMiddleware.AlterationsLogPropertyKey, log);
 70
 71        // Build a new workflow execution pipeline.
 372        var pipelineBuilder = new WorkflowExecutionPipelineBuilder(serviceProvider);
 373        workflowExecutionPipeline.ConfigurePipelineBuilder(pipelineBuilder);
 74
 75        // Replace the terminal DefaultActivitySchedulerMiddleware with the RunAlterationsMiddleware terminal.
 376        pipelineBuilder.ReplaceTerminal<RunAlterationsMiddleware>();
 77
 78        // Build modified pipeline.
 379        var pipeline = pipelineBuilder.Build();
 80
 81        // Execute the pipeline.
 382        await pipeline(workflowExecutionContext);
 83
 84        // Extract workflow state.
 385        workflowState = workflowStateExtractor.Extract(workflowExecutionContext);
 86
 87        // Commit workflow state.
 388        await commitStateHandler.CommitAsync(workflowExecutionContext, workflowState, cancellationToken);
 89
 90        // Apply updated workflow state.
 91        // TODO: Importing back into the workflow runtime makes sense, but this also causes another SAVE ction of the wo
 92        // Can we avoid this? Perhaps we need more granular control over when we purge and when we save to DB.
 393        await workflowClient.ImportStateAsync(workflowState, cancellationToken);
 94
 95        // Check if the workflow has scheduled work.
 396        result.WorkflowHasScheduledWork = workflowExecutionContext.Scheduler.HasAny;
 97
 398        return result;
 399    }
 100}