< Summary

Information
Class: Elsa.Workflows.Activities.Flowchart.Extensions.ActivityExecutionContextExtensions
Assembly: Elsa.Workflows.Core
File(s): /home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Extensions/ActivityExecutionContextExtensions.cs
Line coverage
89%
Covered lines: 44
Uncovered lines: 5
Coverable lines: 49
Total lines: 135
Line coverage: 89.7%
Branch coverage
77%
Covered branches: 28
Total branches: 36
Branch coverage: 77.7%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
GetStartActivity(...)90%1010100%
GetTriggerActivity(...)100%22100%
GetExplicitStartActivity(...)100%11100%
GetCanStartWorkflowActivity(...)100%11100%
HasPendingWork(...)100%66100%
GetFlowGraph(...)100%11100%
CancelInboundAncestorsAsync()75%4485.71%
HasUnconsumedTokens(...)75%44100%
HasRunningActivityInstances(...)100%11100%
HasScheduledWork(...)37.5%9875%
HasFaultedChildren(...)100%11100%

File(s)

/home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Extensions/ActivityExecutionContextExtensions.cs

#LineLine coverage
 1using Elsa.Extensions;
 2using Elsa.Workflows.Activities.Flowchart.Models;
 3
 4namespace Elsa.Workflows.Activities.Flowchart.Extensions;
 5
 6public static class ActivityExecutionContextExtensions
 7{
 8    private const string GraphTransientProperty = "FlowGraph";
 9
 10    extension(Activities.Flowchart flowchart)
 11    {
 12        public IActivity? GetStartActivity(string? triggerActivityId)
 13        {
 100714            return flowchart.GetTriggerActivity(triggerActivityId)
 100715                   ?? flowchart.Start
 100716                   ?? flowchart.GetExplicitStartActivity()
 100717                   ?? flowchart.GetCanStartWorkflowActivity()
 100718                   ?? flowchart.GetRootActivity()
 100719                   ?? flowchart.Activities.FirstOrDefault();
 20        }
 21
 22        /// <summary>
 23        /// Gets the activity that was triggered by the specified trigger activity ID.
 24        /// </summary>
 25        public IActivity? GetTriggerActivity(string? triggerActivityId)
 26        {
 100727            return triggerActivityId == null
 100728                ? null :
 182629                flowchart.Activities.FirstOrDefault(x => x.Id == triggerActivityId);
 30        }
 31
 32        /// <summary>
 33        /// Gets the explicit Start activity from the flowchart.
 34        /// </summary>
 35        public IActivity? GetExplicitStartActivity()
 36        {
 89237            return flowchart.Activities.FirstOrDefault(x => x is Start);
 38        }
 39
 40        /// <summary>
 41        /// Gets the first activity marked as "Can Start Workflow".
 42        /// </summary>
 43        public IActivity? GetCanStartWorkflowActivity()
 44        {
 89245            return flowchart.Activities.FirstOrDefault(x => x.GetCanStartWorkflow());
 46        }
 47    }
 48
 49    extension(ActivityExecutionContext context)
 50    {
 51        /// <summary>
 52        /// Checks if there is any pending work for the flowchart.
 53        /// </summary>
 54        public bool HasPendingWork()
 55        {
 97656            return context.HasRunningActivityInstances()
 97657                   || context.HasScheduledWork()
 97658                   || context.HasUnconsumedTokens()
 97659                   || context.HasFaultedChildren();
 60        }
 61
 62        public FlowGraph GetFlowGraph()
 63        {
 64            // Store in TransientProperties so FlowChart is not persisted in WorkflowState
 100765            var flowchart = (Activities.Flowchart)context.Activity;
 100766            var startActivity = flowchart.GetStartActivity(context.WorkflowExecutionContext.TriggerActivityId);
 166267            return context.TransientProperties.GetOrAdd(GraphTransientProperty, () => new FlowGraph(flowchart.Connection
 68        }
 69
 70        public async Task CancelInboundAncestorsAsync(IActivity activity)
 71        {
 3172            if(context.Activity is not Activities.Flowchart)
 073                throw new InvalidOperationException("Activity context is not a flowchart.");
 74
 3175            var flowGraph = context.GetFlowGraph();
 3176            var ancestorActivities = flowGraph.GetAncestorActivities(activity);
 24477            var inboundActivityExecutionContexts = context.WorkflowExecutionContext.ActivityExecutionContexts.Where(x =>
 78
 79            // Cancel each ancestor activity.
 32080            foreach (var activityExecutionContext in inboundActivityExecutionContexts)
 81            {
 12982                await activityExecutionContext.CancelActivityAsync();
 83            }
 3184        }
 85
 86        /// <summary>
 87        /// Checks if the flowchart has any unconsumed tokens.
 88        /// </summary>
 89        public bool HasUnconsumedTokens()
 90        {
 65591            var flowchart = (Activities.Flowchart)context.Activity;
 89692            return flowchart.GetTokenList(context).Any(x => x is { Consumed: false, Blocked: false });
 93        }
 94
 95        /// <summary>
 96        /// Checks if the flowchart has any running activity instances.
 97        /// </summary>
 98        public bool HasRunningActivityInstances()
 99        {
 976100            var flowchart = (Activities.Flowchart)context.Activity;
 3103101            var activityIds = flowchart.Activities.Select(x => x.Id).ToList();
 976102            var children = context.Children;
 4022103            return children.Where(x => activityIds.Contains(x.Activity.Id)).Any(x => x.Status == ActivityStatus.Running)
 104        }
 105
 106        /// <summary>
 107        /// Checks if the flowchart has any scheduled work items.
 108        /// </summary>
 109        public bool HasScheduledWork()
 110        {
 976111            var workflowExecutionContext = context.WorkflowExecutionContext;
 112
 976113            return workflowExecutionContext.Scheduler.List().Any(workItem =>
 976114            {
 321115                var ownerInstanceId = workItem.Owner?.Id;
 976116
 321117                if (ownerInstanceId == null)
 0118                    return false;
 976119
 321120                if (ownerInstanceId == context.Id)
 321121                    return true;
 976122
 0123                var ownerContext = context.WorkflowExecutionContext.ActivityExecutionContexts.First(x => x.Id == ownerIn
 0124                var ancestors = ownerContext.GetAncestors().ToList();
 976125
 0126                return ancestors.Any(x => x == context);
 976127            });
 128        }
 129
 130        public bool HasFaultedChildren()
 131        {
 1631132            return context.Children.Any(x => x.Status == ActivityStatus.Faulted);
 133        }
 134    }
 135}