Merge pull request #6213 from elsa-workflows/bug/6170

Refactor activity cancellation and bookmark handling.
This commit is contained in:
Sipke Schoorstra 2024-12-14 21:09:15 +01:00 committed by GitHub
commit 5d92c5760f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 11 additions and 34 deletions

View file

@ -1,7 +1,6 @@
using System.Collections.Immutable;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using Elsa.Extensions;
using Elsa.Workflows.Attributes;
using Elsa.Workflows.Signals;
using Elsa.Workflows.UIHints;
@ -18,7 +17,7 @@ namespace Elsa.Workflows.Activities;
public class Fork : Activity
{
/// <inheritdoc />
public Fork([CallerFilePath] string? source = default, [CallerLineNumber] int? line = default) : base(source, line)
public Fork([CallerFilePath] string? source = null, [CallerLineNumber] int? line = null) : base(source, line)
{
// Handle break signals directly instead of using the BreakBehavior. The behavior stops propagation of the signal, which is not what we want.
OnSignalReceived<BreakSignal>(OnBreakSignalReceived);
@ -48,13 +47,7 @@ public class Fork : Activity
if (isBreaking)
{
// Remove all bookmarks from other branches.
RemoveBookmarks(targetContext);
// Signal activity completion.
await CompleteAsync(targetContext);
// Exit.
return;
}
@ -75,37 +68,15 @@ public class Fork : Activity
switch (joinMode)
{
case ForkJoinMode.WaitAny:
{
// Remove all bookmarks from other branches.
RemoveBookmarks(targetContext);
// Signal activity completion.
await CompleteAsync(targetContext);
}
break;
case ForkJoinMode.WaitAll:
{
var allSet = allChildActivityIds.All(x => completedActivityIds.Contains(x));
if (allSet)
// Signal activity completion.
await CompleteAsync(targetContext);
}
if (allSet) await CompleteAsync(targetContext);
break;
}
}
private void RemoveBookmarks(ActivityExecutionContext context)
{
// Find all descendants for each branch and remove them as well as any associated bookmarks.
var workflowExecutionContext = context.WorkflowExecutionContext;
var forkNode = context.ActivityNode;
var branchNodes = forkNode.Children;
var branchDescendantActivityIds = branchNodes.SelectMany(x => x.Flatten()).Select(x => x.Activity.Id).ToHashSet();
workflowExecutionContext.Bookmarks.RemoveWhere(x => branchDescendantActivityIds.Contains(x.ActivityId));
}
private void OnBreakSignalReceived(BreakSignal signal, SignalContext signalContext)
{
signalContext.ReceiverActivityExecutionContext.SetIsBreaking();

View file

@ -23,13 +23,19 @@ public partial class ActivityExecutionContext
ClearBookmarks();
ClearCompletionCallbacks();
WorkflowExecutionContext.Bookmarks.RemoveWhere(x => x.ActivityNodeId == NodeId);
// Add an execution log entry.
AddExecutionLogEntry("Canceled", payload: JournalData);
await this.SendSignalAsync(new CancelSignal());
await CancelChildActivitiesAsync();
// ReSharper disable once MethodSupportsCancellation
await _publisher.SendAsync(new ActivityCancelled(this));
}
private async Task CancelChildActivitiesAsync()
{
var childContexts = WorkflowExecutionContext.ActivityExecutionContexts.Where(x => x.ParentActivityExecutionContext == this && x.CanCancelActivity()).ToList();
foreach (var childContext in childContexts)
await childContext.CancelActivityAsync();
}
}