< Summary

Information
Class: Elsa.Workflows.Activities.Fork
Assembly: Elsa.Workflows.Core
File(s): /home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Workflows.Core/Activities/Fork.cs
Line coverage
31%
Covered lines: 10
Uncovered lines: 22
Coverable lines: 32
Total lines: 95
Line coverage: 31.2%
Branch coverage
16%
Covered branches: 2
Total branches: 12
Branch coverage: 16.6%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
get_JoinMode()100%11100%
get_Branches()100%11100%
ExecuteAsync()100%22100%
CompleteChildAsync()0%7280%
OnBreakSignalReceived(...)100%210%

File(s)

/home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Workflows.Core/Activities/Fork.cs

#LineLine coverage
 1using System.Collections.Immutable;
 2using System.ComponentModel;
 3using System.Runtime.CompilerServices;
 4using Elsa.Extensions;
 5using Elsa.Workflows.Attributes;
 6using Elsa.Workflows.Signals;
 7using Elsa.Workflows.UIHints;
 8using JetBrains.Annotations;
 9
 10namespace Elsa.Workflows.Activities;
 11
 12/// <summary>
 13/// Branch execution into multiple branches.
 14/// </summary>
 15[Activity("Elsa", "Control Flow", "Branch execution into multiple branches.")]
 16[PublicAPI]
 17[Browsable(false)]
 18public class Fork : Activity
 19{
 20    /// <inheritdoc />
 421    public Fork([CallerFilePath] string? source = null, [CallerLineNumber] int? line = null) : base(source, line)
 22    {
 23        // Handle break signals directly instead of using the BreakBehavior. The behavior stops propagation of the signa
 424        OnSignalReceived<BreakSignal>(OnBreakSignalReceived);
 425    }
 26
 27    /// <summary>
 28    /// Controls when this activity yields control back to its parent activity.
 29    /// </summary>
 30    [Input(
 31        Description = "Controls when this activity yields control back to its parent activity.",
 32        UIHint = InputUIHints.DropDown
 33    )]
 1034    public ForkJoinMode JoinMode { get; set; } = ForkJoinMode.WaitAll;
 35
 36    /// <summary>
 37    /// The branches to schedule.
 38    /// </summary>
 1839    public ICollection<IActivity> Branches { get; set; } = new List<IActivity>();
 40
 41    /// <inheritdoc />
 42    protected override async ValueTask ExecuteAsync(ActivityExecutionContext context)
 43    {
 44        // If there are no branches, complete immediately
 445        if (Branches.Count == 0)
 46        {
 147            await context.CompleteActivityAsync();
 148            return;
 49        }
 50
 351        await context.ScheduleActivities(Branches, CompleteChildAsync);
 452    }
 53
 54    private async ValueTask CompleteChildAsync(ActivityCompletedContext context)
 55    {
 056        var targetContext = context.TargetContext;
 057        var isBreaking = targetContext.GetIsBreaking();
 58
 059        if (isBreaking)
 60        {
 061            await CompleteAsync(targetContext);
 062            return;
 63        }
 64
 065        var childContext = context.ChildContext;
 066        var completedChildActivityId = childContext.Activity.Id;
 67
 68        // Append activity to the set of completed activities.
 069        var completedActivityIds = targetContext.UpdateProperty<HashSet<string>>("Completed", set =>
 070        {
 071            set ??= new();
 072            set.Add(completedChildActivityId);
 073            return set;
 074        });
 75
 076        var allChildActivityIds = Branches.Select(x => x.Id).ToImmutableHashSet();
 077        var joinMode = JoinMode;
 78
 79        switch (joinMode)
 80        {
 81            case ForkJoinMode.WaitAny:
 082                await CompleteAsync(targetContext);
 083                break;
 84            case ForkJoinMode.WaitAll:
 085                var allSet = allChildActivityIds.All(x => completedActivityIds.Contains(x));
 086                if (allSet) await CompleteAsync(targetContext);
 87                break;
 88        }
 089    }
 90
 91    private void OnBreakSignalReceived(BreakSignal signal, SignalContext signalContext)
 92    {
 093        signalContext.ReceiverActivityExecutionContext.SetIsBreaking();
 094    }
 95}