From e5c397d4fb873806af09f07e9aa216eb932b2643 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Mon, 14 Apr 2025 11:57:14 +0200 Subject: [PATCH] Refactor workflow instance creation and execution logic. (#6586) Updated `CreateAndRunInstanceAsync` to separate instance creation and execution with locking to handle nested workflow scenarios. Made `RunInstanceAsync` public to facilitate reuse in the distributed workflow client. --- .../Services/DistributedWorkflowClient.cs | 23 +++++++++++++++++-- .../Services/LocalWorkflowClient.cs | 2 +- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/modules/Elsa.Workflows.Runtime.Distributed/Services/DistributedWorkflowClient.cs b/src/modules/Elsa.Workflows.Runtime.Distributed/Services/DistributedWorkflowClient.cs index a9468d11d..d483819a5 100644 --- a/src/modules/Elsa.Workflows.Runtime.Distributed/Services/DistributedWorkflowClient.cs +++ b/src/modules/Elsa.Workflows.Runtime.Distributed/Services/DistributedWorkflowClient.cs @@ -31,8 +31,27 @@ public class DistributedWorkflowClient( public async Task CreateAndRunInstanceAsync(CreateAndRunWorkflowInstanceRequest request, CancellationToken cancellationToken = default) { - var result = await _localWorkflowClient.CreateAndRunInstanceAsync(request, cancellationToken); - return result; + var createRequest = new CreateWorkflowInstanceRequest + { + Properties = request.Properties, + CorrelationId = request.CorrelationId, + Name = request.Name, + Input = request.Input, + WorkflowDefinitionHandle = request.WorkflowDefinitionHandle, + ParentId = request.ParentId + }; + var workflowInstance = await _localWorkflowClient.CreateInstanceInternalAsync(createRequest, cancellationToken); + + // We need to lock newly created workflow instances too, because it might dispatch child workflows that attempt to resume the parent workflow. + // For example, when using a DispatchWorkflow activity configured to wait for the dispatched workflow to complete. + return await WithLockAsync(async () => await _localWorkflowClient.RunInstanceAsync(workflowInstance, new() + { + Input = request.Input, + Variables = request.Variables, + Properties = request.Properties, + TriggerActivityId = request.TriggerActivityId, + ActivityHandle = request.ActivityHandle + }, cancellationToken)); } public async Task CancelAsync(CancellationToken cancellationToken = default) diff --git a/src/modules/Elsa.Workflows.Runtime/Services/LocalWorkflowClient.cs b/src/modules/Elsa.Workflows.Runtime/Services/LocalWorkflowClient.cs index 6d9a182f8..223468d2c 100644 --- a/src/modules/Elsa.Workflows.Runtime/Services/LocalWorkflowClient.cs +++ b/src/modules/Elsa.Workflows.Runtime/Services/LocalWorkflowClient.cs @@ -104,7 +104,7 @@ public class LocalWorkflowClient( return workflowInstanceManager.ExistsAsync(workflowInstanceId, cancellationToken); } - private async Task RunInstanceAsync(WorkflowInstance workflowInstance, RunWorkflowInstanceRequest request, CancellationToken cancellationToken = default) + public async Task RunInstanceAsync(WorkflowInstance workflowInstance, RunWorkflowInstanceRequest request, CancellationToken cancellationToken = default) { var workflowState = workflowInstance.WorkflowState;