< Summary

Information
Class: Elsa.Workflows.WorkflowRunner
Assembly: Elsa.Workflows.Core
File(s): /home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Workflows.Core/Services/WorkflowRunner.cs
Line coverage
80%
Covered lines: 97
Uncovered lines: 24
Coverable lines: 121
Total lines: 227
Line coverage: 80.1%
Branch coverage
68%
Covered branches: 41
Total branches: 60
Branch coverage: 68.3%
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()100%11100%
RunAsync()100%210%
RunAsync()100%210%
RunAsync()100%11100%
RunAsync()100%210%
RunAsync()100%1414100%
RunAsync()100%11100%
RunAsync()100%11100%
RunAsync()50%774474.35%
RunAsync()100%66100%

File(s)

/home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Workflows.Core/Services/WorkflowRunner.cs

#LineLine coverage
 1using Elsa.Extensions;
 2using Elsa.Mediator.Contracts;
 3using Elsa.Workflows.Activities;
 4using Elsa.Workflows.CommitStates;
 5using Elsa.Workflows.Memory;
 6using Elsa.Workflows.Models;
 7using Elsa.Workflows.Notifications;
 8using Elsa.Workflows.Options;
 9using Elsa.Workflows.State;
 10using Microsoft.Extensions.Logging;
 11
 12namespace Elsa.Workflows;
 13
 14/// <inheritdoc />
 49415public class WorkflowRunner(
 49416    IServiceProvider serviceProvider,
 49417    IWorkflowExecutionPipeline pipeline,
 49418    IWorkflowStateExtractor workflowStateExtractor,
 49419    IWorkflowBuilderFactory workflowBuilderFactory,
 49420    IWorkflowGraphBuilder workflowGraphBuilder,
 49421    IIdentityGenerator identityGenerator,
 49422    INotificationSender notificationSender,
 49423    ILoggerStateGenerator<WorkflowExecutionContext> loggerStateGenerator,
 49424    ICommitStateHandler commitStateHandler,
 49425    ILogger<WorkflowRunner> logger)
 26    : IWorkflowRunner
 27{
 28    /// <inheritdoc />
 29    public async Task<RunWorkflowResult> RunAsync(IActivity activity, RunWorkflowOptions? options = null, CancellationTo
 30    {
 10931        var workflow = Workflow.FromActivity(activity);
 10932        var workflowGraph = await workflowGraphBuilder.BuildAsync(workflow, cancellationToken);
 10933        return await RunAsync(workflowGraph, options, cancellationToken);
 10934    }
 35
 36    /// <inheritdoc />
 37    public async Task<RunWorkflowResult> RunAsync(IWorkflow workflow, RunWorkflowOptions? options = null, CancellationTo
 38    {
 039        var builder = workflowBuilderFactory.CreateBuilder();
 040        var workflowDefinition = await builder.BuildWorkflowAsync(workflow, cancellationToken);
 041        return await RunAsync(workflowDefinition, options, cancellationToken);
 042    }
 43
 44    /// <inheritdoc />
 45    public async Task<RunWorkflowResult<TResult>> RunAsync<TResult>(WorkflowBase<TResult> workflow, RunWorkflowOptions? 
 46    {
 047        var result = await RunAsync((IWorkflow)workflow, options, cancellationToken);
 048        return new(result.WorkflowExecutionContext, result.WorkflowState, result.Workflow, (TResult)result.Result!, resu
 049    }
 50
 51    /// <inheritdoc />
 52    public async Task<RunWorkflowResult> RunAsync<T>(RunWorkflowOptions? options = null, CancellationToken cancellationT
 53    {
 254        var builder = workflowBuilderFactory.CreateBuilder();
 255        var workflowDefinition = await builder.BuildWorkflowAsync<T>(cancellationToken);
 256        return await RunAsync(workflowDefinition, options, cancellationToken);
 257    }
 58
 59    /// <inheritdoc />
 60    public async Task<TResult> RunAsync<T, TResult>(RunWorkflowOptions? options = null, CancellationToken cancellationTo
 61    {
 062        var builder = workflowBuilderFactory.CreateBuilder();
 063        var workflow = await builder.BuildWorkflowAsync<T>(cancellationToken);
 064        var result = await RunAsync(workflow, options, cancellationToken);
 065        return (TResult)result.Result!;
 066    }
 67
 68    /// <inheritdoc />
 69    public async Task<RunWorkflowResult> RunAsync(WorkflowGraph workflowGraph, RunWorkflowOptions? options = null, Cance
 70    {
 71        // Set up a workflow execution context.
 37672        var instanceId = options?.WorkflowInstanceId ?? identityGenerator.GenerateId();
 37673        var input = options?.Input;
 37674        var properties = options?.Properties;
 37675        var correlationId = options?.CorrelationId;
 37676        var triggerActivityId = options?.TriggerActivityId;
 37677        var parentWorkflowInstanceId = options?.ParentWorkflowInstanceId;
 37678        var workflowExecutionContext = await WorkflowExecutionContext.CreateAsync(
 37679            serviceProvider,
 37680            workflowGraph,
 37681            instanceId,
 37682            correlationId,
 37683            parentWorkflowInstanceId,
 37684            input,
 37685            properties,
 37686            null,
 37687            triggerActivityId,
 37688            cancellationToken);
 89
 90        // Schedule the first activity.
 37691        workflowExecutionContext.ScheduleWorkflow();
 92
 37693        return await RunAsync(workflowExecutionContext);
 37694    }
 95
 96    /// <inheritdoc />
 97    public async Task<RunWorkflowResult> RunAsync(Workflow workflow, RunWorkflowOptions? options = null, CancellationTok
 98    {
 299        var workflowGraph = await workflowGraphBuilder.BuildAsync(workflow, cancellationToken);
 2100        return await RunAsync(workflowGraph, options, cancellationToken);
 2101    }
 102
 103    /// <inheritdoc />
 104    public async Task<RunWorkflowResult> RunAsync(Workflow workflow, WorkflowState workflowState, RunWorkflowOptions? op
 105    {
 2106        var workflowGraph = await workflowGraphBuilder.BuildAsync(workflow, cancellationToken);
 2107        return await RunAsync(workflowGraph, workflowState, options, cancellationToken);
 2108    }
 109
 110    /// <inheritdoc />
 111    public async Task<RunWorkflowResult> RunAsync(WorkflowGraph workflowGraph, WorkflowState workflowState, RunWorkflowO
 112    {
 113        // Create a workflow execution context.
 133114        var input = options?.Input;
 133115        var variables = options?.Variables;
 133116        var properties = options?.Properties;
 133117        var correlationId = options?.CorrelationId ?? workflowState.CorrelationId;
 133118        var triggerActivityId = options?.TriggerActivityId;
 133119        var parentWorkflowInstanceId = options?.ParentWorkflowInstanceId;
 133120        var workflowExecutionContext = await WorkflowExecutionContext.CreateAsync(
 133121            serviceProvider,
 133122            workflowGraph,
 133123            workflowState,
 133124            correlationId,
 133125            parentWorkflowInstanceId,
 133126            input,
 133127            properties,
 133128            null,
 133129            triggerActivityId,
 133130            cancellationToken);
 131
 133132        var bookmarkId = options?.BookmarkId;
 133133        var activityHandle = options?.ActivityHandle;
 134
 133135        if (!string.IsNullOrEmpty(bookmarkId))
 136        {
 78137            var bookmark = workflowState.Bookmarks.FirstOrDefault(x => x.Id == bookmarkId);
 138
 39139            if (bookmark != null)
 39140                workflowExecutionContext.ScheduleBookmark(bookmark);
 141        }
 94142        else if (activityHandle != null)
 143        {
 0144            if (!string.IsNullOrEmpty(activityHandle.ActivityInstanceId))
 145            {
 0146                var activityExecutionContext = workflowExecutionContext.ActivityExecutionContexts.FirstOrDefault(x => x.
 0147                                               ?? throw new("No activity execution context found with the specified ID."
 0148                workflowExecutionContext.ScheduleActivityExecutionContext(activityExecutionContext);
 149            }
 150            else
 151            {
 0152                var activity = workflowExecutionContext.FindActivity(activityHandle);
 0153                if (activity != null) workflowExecutionContext.ScheduleActivity(activity);
 154            }
 155        }
 94156        else if (workflowExecutionContext.Scheduler.HasAny)
 157        {
 158            // Do nothing. The scheduler already has activities to schedule.
 159        }
 160        else
 161        {
 162            // Check if there are any interrupted activities.
 94163            var interruptedActivityExecutionContexts = workflowExecutionContext.ActivityExecutionContexts.Where(x => x.I
 164
 94165            if (interruptedActivityExecutionContexts.Count > 0)
 166            {
 167                // Schedule the interrupted activities.
 0168                foreach (var pendingActivityExecutionContext in interruptedActivityExecutionContexts)
 0169                    workflowExecutionContext.ScheduleActivityExecutionContext(pendingActivityExecutionContext);
 170            }
 171            else
 172            {
 173                // Nothing was scheduled. Schedule the workflow itself.
 94174                var vars = variables?.Select(x => new Variable(x.Key, x.Value)).ToList();
 94175                workflowExecutionContext.ScheduleWorkflow(variables: vars);
 176            }
 177        }
 178
 179        // Set variables, if any.
 133180        if (variables != null)
 181        {
 0182            var rootContext = workflowExecutionContext.ActivityExecutionContexts.FirstOrDefault(x => x.ParentActivityExe
 183
 0184            if (rootContext != null)
 185            {
 0186                foreach (var variable in variables)
 0187                    rootContext.SetDynamicVariable(variable.Key, variable.Value);
 188            }
 189        }
 190
 133191        return await RunAsync(workflowExecutionContext);
 133192    }
 193
 194    /// <inheritdoc />
 195    public async Task<RunWorkflowResult> RunAsync(WorkflowExecutionContext workflowExecutionContext)
 196    {
 509197        var loggerState = loggerStateGenerator.GenerateLoggerState(workflowExecutionContext);
 509198        using var loggingScope = logger.BeginScope(loggerState);
 509199        var workflow = workflowExecutionContext.Workflow;
 509200        var cancellationToken = workflowExecutionContext.CancellationToken;
 201
 509202        await notificationSender.SendAsync(new WorkflowExecuting(workflow, workflowExecutionContext), cancellationToken)
 203
 204        // If the status is Pending, it means the workflow is started for the first time.
 509205        if (workflowExecutionContext.SubStatus == WorkflowSubStatus.Pending)
 206        {
 470207            workflowExecutionContext.TransitionTo(WorkflowSubStatus.Executing);
 470208            await notificationSender.SendAsync(new WorkflowStarted(workflow, workflowExecutionContext), cancellationToke
 209        }
 210
 509211        await pipeline.ExecuteAsync(workflowExecutionContext);
 509212        var workflowState = workflowStateExtractor.Extract(workflowExecutionContext);
 213
 509214        if (workflowState.Status == WorkflowStatus.Finished)
 215        {
 461216            await notificationSender.SendAsync(new WorkflowFinished(workflow, workflowState, workflowExecutionContext), 
 217        }
 218
 509219        var result = workflow.ResultVariable?.Get(workflowExecutionContext.MemoryRegister);
 509220        var workflowExecutionLogEntries = workflowExecutionContext.ExecutionLog.ToList();
 509221        var activityExecutionContexts = workflowExecutionContext.ActivityExecutionContexts.ToList();
 509222        var journal = new Journal(workflowExecutionLogEntries, activityExecutionContexts);
 509223        await notificationSender.SendAsync(new WorkflowExecuted(workflow, workflowState, workflowExecutionContext), canc
 509224        await commitStateHandler.CommitAsync(workflowExecutionContext, workflowState, cancellationToken);
 509225        return new(workflowExecutionContext, workflowState, workflowExecutionContext.Workflow, result, journal);
 509226    }
 227}