diff --git a/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Activities/Flowchart.Counters.cs b/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Activities/Flowchart.Counters.cs index 06f3ec9df7..c6742a04d5 100644 --- a/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Activities/Flowchart.Counters.cs +++ b/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Activities/Flowchart.Counters.cs @@ -138,6 +138,16 @@ private async ValueTask ProcessChildCompletedAsync(ActivityExecutionContext flow return; } + // Check if the completed activity is a direct child of this flowchart. + // If not, skip flowchart-specific processing as the activity is managed by an intermediate container (e.g., sub-process). + if (!IsDirectChild(flowchartContext, completedActivityContext)) + { + // The activity is not a direct child, so we don't process its outbound connections. + // Instead, just check if the flowchart should complete. + await CompleteIfNoPendingWorkAsync(flowchartContext); + return; + } + // Schedule the outbound activities var flowGraph = GetFlowGraph(flowchartContext); var flowScope = GetFlowScope(flowchartContext); diff --git a/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Activities/Flowchart.Tokens.cs b/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Activities/Flowchart.Tokens.cs index 127fe1e0e1..f2d4beb061 100644 --- a/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Activities/Flowchart.Tokens.cs +++ b/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Activities/Flowchart.Tokens.cs @@ -13,14 +13,27 @@ private async ValueTask OnChildCompletedTokenBasedLogicAsync(ActivityCompletedCo { var flowContext = ctx.TargetContext; var completedActivity = ctx.ChildContext.Activity; + var completedActivityContext = ctx.ChildContext; var flowGraph = flowContext.GetFlowGraph(); var tokens = GetTokenList(flowContext); // If the completed activity is a terminal node, complete the flowchart immediately. if (completedActivity is ITerminalNode) { - tokens.Clear(); - await flowContext.CompleteActivityAsync(); + await ClearTokensAndCompleteFlowchartAsync(flowContext, tokens); + return; + } + + // Check if the completed activity is a direct child of this flowchart. + // If not, skip flowchart-specific processing as the activity is managed by an intermediate container (e.g., sub-process). + if (!IsDirectChild(flowContext, completedActivityContext)) + { + // The activity is not a direct child, so we don't process its tokens. + // Instead, just check if the flowchart should complete. + if (!flowContext.HasPendingWork()) + { + await ClearTokensAndCompleteFlowchartAsync(flowContext, tokens); + } return; } @@ -151,14 +164,22 @@ private async ValueTask OnChildCompletedTokenBasedLogicAsync(ActivityCompletedCo // Complete flowchart if no pending work. if (!flowContext.HasPendingWork()) { - tokens.Clear(); - await flowContext.CompleteActivityAsync(); + await ClearTokensAndCompleteFlowchartAsync(flowContext, tokens); } // Purge consumed tokens for the completed activity. tokens.RemoveWhere(t => t.ToActivityId == completedActivity.Id && t.Consumed); } + /// + /// Clears all tokens and completes the flowchart. + /// + private static async ValueTask ClearTokensAndCompleteFlowchartAsync(ActivityExecutionContext flowContext, List tokens) + { + tokens.Clear(); + await flowContext.CompleteActivityAsync(); + } + private async ValueTask OnTokenFlowActivityCanceledAsync(CancelSignal signal, SignalContext context) { var flowchartContext = context.ReceiverActivityExecutionContext; diff --git a/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Activities/Flowchart.cs b/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Activities/Flowchart.cs index 08fee20280..e06046b8d5 100644 --- a/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Activities/Flowchart.cs +++ b/src/modules/Elsa.Workflows.Core/Activities/Flowchart/Activities/Flowchart.cs @@ -118,6 +118,17 @@ private async Task CompleteIfNoPendingWorkAsync(ActivityExecutionContext context } } + /// + /// Checks if the completed activity is a direct child of the flowchart. + /// + /// The flowchart's execution context. + /// The completed activity's execution context. + /// True if the activity is a direct child; otherwise, false. + private static bool IsDirectChild(ActivityExecutionContext flowchartContext, ActivityExecutionContext completedActivityContext) + { + return completedActivityContext.ParentActivityExecutionContext == flowchartContext; + } + private static ValueTask ExecuteBasedOnMode(ActivityExecutionContext context, Func tokenBasedAction, Func counterBasedAction) { var mode = GetEffectiveExecutionMode(context);