< 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
87%
Covered lines: 28
Uncovered lines: 4
Coverable lines: 32
Total lines: 95
Line coverage: 87.5%
Branch coverage
83%
Covered branches: 10
Total branches: 12
Branch coverage: 83.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%
get_JoinMode()100%11100%
get_Branches()100%11100%
ExecuteAsync()100%22100%
CompleteChildAsync()62.5%9880%
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 />
 17321    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
 17324        OnSignalReceived<BreakSignal>(OnBreakSignalReceived);
 17325    }
 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    )]
 29934    public ForkJoinMode JoinMode { get; set; } = ForkJoinMode.WaitAll;
 35
 36    /// <summary>
 37    /// The branches to schedule.
 38    /// </summary>
 109339    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
 945        if (Branches.Count == 0)
 46        {
 147            await context.CompleteActivityAsync();
 148            return;
 49        }
 50
 851        await context.ScheduleActivities(Branches, CompleteChildAsync);
 952    }
 53
 54    private async ValueTask CompleteChildAsync(ActivityCompletedContext context)
 55    {
 456        var targetContext = context.TargetContext;
 457        var isBreaking = targetContext.GetIsBreaking();
 58
 459        if (isBreaking)
 60        {
 061            await CompleteAsync(targetContext);
 062            return;
 63        }
 64
 465        var childContext = context.ChildContext;
 466        var completedChildActivityId = childContext.Activity.Id;
 67
 68        // Append activity to the set of completed activities.
 469        var completedActivityIds = targetContext.UpdateProperty<HashSet<string>>("Completed", set =>
 470        {
 471            set ??= new();
 472            set.Add(completedChildActivityId);
 473            return set;
 474        });
 75
 1376        var allChildActivityIds = Branches.Select(x => x.Id).ToImmutableHashSet();
 477        var joinMode = JoinMode;
 78
 79        switch (joinMode)
 80        {
 81            case ForkJoinMode.WaitAny:
 382                await CompleteAsync(targetContext);
 383                break;
 84            case ForkJoinMode.WaitAll:
 385                var allSet = allChildActivityIds.All(x => completedActivityIds.Contains(x));
 286                if (allSet) await CompleteAsync(targetContext);
 87                break;
 88        }
 489    }
 90
 91    private void OnBreakSignalReceived(BreakSignal signal, SignalContext signalContext)
 92    {
 093        signalContext.ReceiverActivityExecutionContext.SetIsBreaking();
 094    }
 95}