< 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
81%
Covered lines: 107
Uncovered lines: 24
Coverable lines: 131
Total lines: 238
Line coverage: 81.6%
Branch coverage
69%
Covered branches: 50
Total branches: 72
Branch coverage: 69.4%
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%2020100%
RunAsync()100%11100%
RunAsync()100%11100%
RunAsync()50%765078.26%
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 />
 49515public class WorkflowRunner(
 49516    IServiceProvider serviceProvider,
 49517    IWorkflowExecutionPipeline pipeline,
 49518    IWorkflowStateExtractor workflowStateExtractor,
 49519    IWorkflowBuilderFactory workflowBuilderFactory,
 49520    IWorkflowGraphBuilder workflowGraphBuilder,
 49521    IIdentityGenerator identityGenerator,
 49522    INotificationSender notificationSender,
 49523    ILoggerStateGenerator<WorkflowExecutionContext> loggerStateGenerator,
 49524    ICommitStateHandler commitStateHandler,
 49525    ILogger<WorkflowRunner> logger)
 26    : IWorkflowRunner
 27{
 28    /// <inheritdoc />
 29    public async Task<RunWorkflowResult> RunAsync(IActivity activity, RunWorkflowOptions? options = null, CancellationTo
 30    {
 11031        var workflow = Workflow.FromActivity(activity);
 11032        var workflowGraph = await workflowGraphBuilder.BuildAsync(workflow, cancellationToken);
 11033        return await RunAsync(workflowGraph, options, cancellationToken);
 11034    }
 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.
 37772        var instanceId = options?.WorkflowInstanceId ?? identityGenerator.GenerateId();
 37773        var input = options?.Input;
 37774        var properties = options?.Properties;
 37775        var correlationId = options?.CorrelationId;
 37776        var triggerActivityId = options?.TriggerActivityId;
 37777        var parentWorkflowInstanceId = options?.ParentWorkflowInstanceId;
 37778        var workflowExecutionContext = await WorkflowExecutionContext.CreateAsync(
 37779            serviceProvider,
 37780            workflowGraph,
 37781            instanceId,
 37782            correlationId,
 37783            parentWorkflowInstanceId,
 37784            input,
 37785            properties,
 37786            null,
 37787            triggerActivityId,
 37788            cancellationToken);
 89
 90        // Schedule the first activity.
 37791        workflowExecutionContext.ScheduleWorkflow(
 37792            schedulingActivityExecutionId: options?.SchedulingActivityExecutionId,
 37793            schedulingWorkflowInstanceId: options?.SchedulingWorkflowInstanceId,
 37794            schedulingCallStackDepth: options?.SchedulingCallStackDepth);
 95
 37796        return await RunAsync(workflowExecutionContext);
 37797    }
 98
 99    /// <inheritdoc />
 100    public async Task<RunWorkflowResult> RunAsync(Workflow workflow, RunWorkflowOptions? options = null, CancellationTok
 101    {
 2102        var workflowGraph = await workflowGraphBuilder.BuildAsync(workflow, cancellationToken);
 2103        return await RunAsync(workflowGraph, options, cancellationToken);
 2104    }
 105
 106    /// <inheritdoc />
 107    public async Task<RunWorkflowResult> RunAsync(Workflow workflow, WorkflowState workflowState, RunWorkflowOptions? op
 108    {
 2109        var workflowGraph = await workflowGraphBuilder.BuildAsync(workflow, cancellationToken);
 2110        return await RunAsync(workflowGraph, workflowState, options, cancellationToken);
 2111    }
 112
 113    /// <inheritdoc />
 114    public async Task<RunWorkflowResult> RunAsync(WorkflowGraph workflowGraph, WorkflowState workflowState, RunWorkflowO
 115    {
 116        // Create a workflow execution context.
 133117        var input = options?.Input;
 133118        var variables = options?.Variables;
 133119        var properties = options?.Properties;
 133120        var correlationId = options?.CorrelationId ?? workflowState.CorrelationId;
 133121        var triggerActivityId = options?.TriggerActivityId;
 133122        var parentWorkflowInstanceId = options?.ParentWorkflowInstanceId;
 133123        var workflowExecutionContext = await WorkflowExecutionContext.CreateAsync(
 133124            serviceProvider,
 133125            workflowGraph,
 133126            workflowState,
 133127            correlationId,
 133128            parentWorkflowInstanceId,
 133129            input,
 133130            properties,
 133131            null,
 133132            triggerActivityId,
 133133            cancellationToken);
 134
 133135        var bookmarkId = options?.BookmarkId;
 133136        var activityHandle = options?.ActivityHandle;
 137
 133138        if (!string.IsNullOrEmpty(bookmarkId))
 139        {
 78140            var bookmark = workflowState.Bookmarks.FirstOrDefault(x => x.Id == bookmarkId);
 141
 39142            if (bookmark != null)
 39143                workflowExecutionContext.ScheduleBookmark(bookmark);
 144        }
 94145        else if (activityHandle != null)
 146        {
 0147            if (!string.IsNullOrEmpty(activityHandle.ActivityInstanceId))
 148            {
 0149                var activityExecutionContext = workflowExecutionContext.ActivityExecutionContexts.FirstOrDefault(x => x.
 0150                                               ?? throw new("No activity execution context found with the specified ID."
 0151                workflowExecutionContext.ScheduleActivityExecutionContext(activityExecutionContext);
 152            }
 153            else
 154            {
 0155                var activity = workflowExecutionContext.FindActivity(activityHandle);
 0156                if (activity != null) workflowExecutionContext.ScheduleActivity(activity);
 157            }
 158        }
 94159        else if (workflowExecutionContext.Scheduler.HasAny)
 160        {
 161            // Do nothing. The scheduler already has activities to schedule.
 162        }
 163        else
 164        {
 165            // Check if there are any interrupted activities.
 94166            var interruptedActivityExecutionContexts = workflowExecutionContext.ActivityExecutionContexts.Where(x => x.I
 167
 94168            if (interruptedActivityExecutionContexts.Count > 0)
 169            {
 170                // Schedule the interrupted activities.
 0171                foreach (var pendingActivityExecutionContext in interruptedActivityExecutionContexts)
 0172                    workflowExecutionContext.ScheduleActivityExecutionContext(pendingActivityExecutionContext);
 173            }
 174            else
 175            {
 176                // Nothing was scheduled. Schedule the workflow itself.
 94177                var vars = variables?.Select(x => new Variable(x.Key, x.Value)).ToList();
 94178                var schedulingActivityExecutionId = options?.SchedulingActivityExecutionId;
 94179                var schedulingWorkflowInstanceId = options?.SchedulingWorkflowInstanceId;
 94180                var schedulingCallStackDepth = options?.SchedulingCallStackDepth;
 181
 94182                workflowExecutionContext.ScheduleWorkflow(
 94183                    variables: vars,
 94184                    schedulingActivityExecutionId: schedulingActivityExecutionId,
 94185                    schedulingWorkflowInstanceId: schedulingWorkflowInstanceId,
 94186                    schedulingCallStackDepth: schedulingCallStackDepth);
 187            }
 188        }
 189
 190        // Set variables, if any.
 133191        if (variables != null)
 192        {
 0193            var rootContext = workflowExecutionContext.ActivityExecutionContexts.FirstOrDefault(x => x.ParentActivityExe
 194
 0195            if (rootContext != null)
 196            {
 0197                foreach (var variable in variables)
 0198                    rootContext.SetDynamicVariable(variable.Key, variable.Value);
 199            }
 200        }
 201
 133202        return await RunAsync(workflowExecutionContext);
 133203    }
 204
 205    /// <inheritdoc />
 206    public async Task<RunWorkflowResult> RunAsync(WorkflowExecutionContext workflowExecutionContext)
 207    {
 510208        var loggerState = loggerStateGenerator.GenerateLoggerState(workflowExecutionContext);
 510209        using var loggingScope = logger.BeginScope(loggerState);
 510210        var workflow = workflowExecutionContext.Workflow;
 510211        var cancellationToken = workflowExecutionContext.CancellationToken;
 212
 510213        await notificationSender.SendAsync(new WorkflowExecuting(workflow, workflowExecutionContext), cancellationToken)
 214
 215        // If the status is Pending, it means the workflow is started for the first time.
 510216        if (workflowExecutionContext.SubStatus == WorkflowSubStatus.Pending)
 217        {
 471218            workflowExecutionContext.TransitionTo(WorkflowSubStatus.Executing);
 471219            await notificationSender.SendAsync(new WorkflowStarted(workflow, workflowExecutionContext), cancellationToke
 220        }
 221
 510222        await pipeline.ExecuteAsync(workflowExecutionContext);
 510223        var workflowState = workflowStateExtractor.Extract(workflowExecutionContext);
 224
 510225        if (workflowState.Status == WorkflowStatus.Finished)
 226        {
 462227            await notificationSender.SendAsync(new WorkflowFinished(workflow, workflowState, workflowExecutionContext), 
 228        }
 229
 510230        var result = workflow.ResultVariable?.Get(workflowExecutionContext.MemoryRegister);
 510231        var workflowExecutionLogEntries = workflowExecutionContext.ExecutionLog.ToList();
 510232        var activityExecutionContexts = workflowExecutionContext.ActivityExecutionContexts.ToList();
 510233        var journal = new Journal(workflowExecutionLogEntries, activityExecutionContexts);
 510234        await notificationSender.SendAsync(new WorkflowExecuted(workflow, workflowState, workflowExecutionContext), canc
 510235        await commitStateHandler.CommitAsync(workflowExecutionContext, workflowState, cancellationToken);
 510236        return new(workflowExecutionContext, workflowState, workflowExecutionContext.Workflow, result, journal);
 510237    }
 238}