From 9c2b57865eba5d01910c1089698cac9faeb03b44 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Wed, 19 May 2021 10:09:01 +0200 Subject: [PATCH] Implement Dispatch Workflow Definition endpoint --- .../Services/IWorkflowLaunchpad.cs | 5 +++ .../Elsa.Core/Services/WorkflowLaunchpad.cs | 8 +++- .../Endpoints/WorkflowDefinitions/Dispatch.cs | 45 +++++++++++++++++++ .../Endpoints/WorkflowDefinitions/Execute.cs | 18 ++++---- .../Endpoints/WorkflowDefinitions/Models.cs | 5 ++- 5 files changed, 68 insertions(+), 13 deletions(-) create mode 100644 src/server/Elsa.Server.Api/Endpoints/WorkflowDefinitions/Dispatch.cs diff --git a/src/core/Elsa.Abstractions/Services/IWorkflowLaunchpad.cs b/src/core/Elsa.Abstractions/Services/IWorkflowLaunchpad.cs index 90f45e066..b37712183 100644 --- a/src/core/Elsa.Abstractions/Services/IWorkflowLaunchpad.cs +++ b/src/core/Elsa.Abstractions/Services/IWorkflowLaunchpad.cs @@ -73,6 +73,11 @@ namespace Elsa.Services /// Executes the specified startable workflow. /// Task ExecuteStartableWorkflowAsync(StartableWorkflow startableWorkflow, object? input, CancellationToken cancellationToken = default); + + /// + /// Dispatches the specified startable workflow. + /// + Task DispatchStartableWorkflowAsync(StartableWorkflow startableWorkflow, object? input, CancellationToken cancellationToken = default); /// /// Collects and executes workflows that are ready for execution. This takes into account both resumable (suspended) workflows as well as startable workflows. diff --git a/src/core/Elsa.Core/Services/WorkflowLaunchpad.cs b/src/core/Elsa.Core/Services/WorkflowLaunchpad.cs index 8d1b686ac..d951ab33d 100644 --- a/src/core/Elsa.Core/Services/WorkflowLaunchpad.cs +++ b/src/core/Elsa.Core/Services/WorkflowLaunchpad.cs @@ -212,9 +212,13 @@ namespace Elsa.Services public async Task DispatchPendingWorkflowAsync(PendingWorkflow pendingWorkflow, object? input, CancellationToken cancellationToken = default) => await _workflowInstanceDispatcher.DispatchAsync(new ExecuteWorkflowInstanceRequest(pendingWorkflow.WorkflowInstanceId, pendingWorkflow.ActivityId, input), cancellationToken); - public async Task ExecuteStartableWorkflowAsync(StartableWorkflow startableWorkflow, object? input, CancellationToken cancellationToken = default) + public async Task ExecuteStartableWorkflowAsync(StartableWorkflow startableWorkflow, object? input, CancellationToken cancellationToken = default) => await _workflowRunner.RunWorkflowAsync(startableWorkflow.WorkflowBlueprint, startableWorkflow.WorkflowInstance, startableWorkflow.ActivityId, input, cancellationToken); + + public async Task DispatchStartableWorkflowAsync(StartableWorkflow startableWorkflow, object? input, CancellationToken cancellationToken = default) { - return await _workflowRunner.RunWorkflowAsync(startableWorkflow.WorkflowBlueprint, startableWorkflow.WorkflowInstance, startableWorkflow.ActivityId, input, cancellationToken); + var pendingWorkflow = new PendingWorkflow(startableWorkflow.WorkflowInstance.Id, startableWorkflow.ActivityId); + await ExecutePendingWorkflowAsync(pendingWorkflow, input, cancellationToken); + return pendingWorkflow; } public async Task> TriggerWorkflowsAsync(CollectWorkflowsContext context, object? input = default, CancellationToken cancellationToken = default) diff --git a/src/server/Elsa.Server.Api/Endpoints/WorkflowDefinitions/Dispatch.cs b/src/server/Elsa.Server.Api/Endpoints/WorkflowDefinitions/Dispatch.cs new file mode 100644 index 000000000..4c35837e1 --- /dev/null +++ b/src/server/Elsa.Server.Api/Endpoints/WorkflowDefinitions/Dispatch.cs @@ -0,0 +1,45 @@ +using System.Threading; +using System.Threading.Tasks; +using Elsa.Server.Api.ActionFilters; +using Elsa.Services; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Swashbuckle.AspNetCore.Annotations; + +namespace Elsa.Server.Api.Endpoints.WorkflowDefinitions +{ + [ApiController] + [ApiVersion("1")] + [Route("v{apiVersion:apiVersion}/workflow-definitions/{workflowDefinitionId}/dispatch")] + [Produces("application/json")] + public class Dispatch : Controller + { + private readonly IWorkflowLaunchpad _workflowLaunchpad; + + public Dispatch(IWorkflowLaunchpad workflowLaunchpad) + { + _workflowLaunchpad = workflowLaunchpad; + } + + [HttpPost] + [ElsaJsonFormatter] + [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(DispatchWorkflowDefinitionResponse))] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [SwaggerOperation( + Summary = "Executes the specified workflow definition.", + Description = "Executes the specified workflow definition.", + OperationId = "WorkflowDefinitions.Execute", + Tags = new[] { "WorkflowDefinitions" }) + ] + public async Task Handle(string workflowDefinitionId, DispatchWorkflowDefinitionRequest request, CancellationToken cancellationToken = default) + { + var startableWorkflow = await _workflowLaunchpad.CollectStartableWorkflowAsync(workflowDefinitionId, request.ActivityId, request.CorrelationId, request.ContextId, default, cancellationToken); + + if (startableWorkflow == null) + return NotFound(); + + var result = await _workflowLaunchpad.DispatchStartableWorkflowAsync(startableWorkflow, request.Input, cancellationToken); + return Ok(new DispatchWorkflowDefinitionResponse(result.WorkflowInstanceId, result.ActivityId)); + } + } +} \ No newline at end of file diff --git a/src/server/Elsa.Server.Api/Endpoints/WorkflowDefinitions/Execute.cs b/src/server/Elsa.Server.Api/Endpoints/WorkflowDefinitions/Execute.cs index 852d318a0..f98a23a6a 100644 --- a/src/server/Elsa.Server.Api/Endpoints/WorkflowDefinitions/Execute.cs +++ b/src/server/Elsa.Server.Api/Endpoints/WorkflowDefinitions/Execute.cs @@ -26,8 +26,7 @@ namespace Elsa.Server.Api.Endpoints.WorkflowDefinitions [HttpPost] [ElsaJsonFormatter] - [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(WorkflowDefinition))] - [SwaggerResponseExample(StatusCodes.Status200OK, typeof(WorkflowDefinitionExample))] + [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(WorkflowDefinitionExecuteResponse))] [ProducesResponseType(StatusCodes.Status404NotFound)] [SwaggerOperation( Summary = "Executes the specified workflow definition.", @@ -35,24 +34,23 @@ namespace Elsa.Server.Api.Endpoints.WorkflowDefinitions OperationId = "WorkflowDefinitions.Execute", Tags = new[] { "WorkflowDefinitions" }) ] - public async Task Handle(string workflowDefinitionId, ExecuteWorkflowDefinitionModel model, CancellationToken cancellationToken = default) + public async Task Handle(string workflowDefinitionId, ExecuteWorkflowDefinitionRequest request, CancellationToken cancellationToken = default) { - var startableWorkflow = await _workflowLaunchpad.CollectStartableWorkflowAsync(workflowDefinitionId, model.ActivityId, model.CorrelationId, model.ContextId, default, cancellationToken); + var startableWorkflow = await _workflowLaunchpad.CollectStartableWorkflowAsync(workflowDefinitionId, request.ActivityId, request.CorrelationId, request.ContextId, default, cancellationToken); if (startableWorkflow == null) return NotFound(); - - var result = await _workflowLaunchpad.ExecuteStartableWorkflowAsync(startableWorkflow, model.Input, cancellationToken); + + var result = await _workflowLaunchpad.ExecuteStartableWorkflowAsync(startableWorkflow, request.Input, cancellationToken); if (Response.HasStarted) return new EmptyResult(); - - return Ok(new - { + + return Ok(new WorkflowDefinitionExecuteResponse( result.Executed, result.ActivityId, result.WorkflowInstance - }); + )); } } } \ No newline at end of file diff --git a/src/server/Elsa.Server.Api/Endpoints/WorkflowDefinitions/Models.cs b/src/server/Elsa.Server.Api/Endpoints/WorkflowDefinitions/Models.cs index 9ef7e528f..e423f3d08 100644 --- a/src/server/Elsa.Server.Api/Endpoints/WorkflowDefinitions/Models.cs +++ b/src/server/Elsa.Server.Api/Endpoints/WorkflowDefinitions/Models.cs @@ -14,5 +14,8 @@ namespace Elsa.Server.Api.Endpoints.WorkflowDefinitions bool IsPublished, bool IsLatest); - public record ExecuteWorkflowDefinitionModel(string? ActivityId, string? CorrelationId, string? ContextId, object? Input); + public record ExecuteWorkflowDefinitionRequest(string? ActivityId, string? CorrelationId, string? ContextId, object? Input); + public record WorkflowDefinitionExecuteResponse(bool Executed, string? ActivityId, WorkflowInstance? WorkflowInstance); + public record DispatchWorkflowDefinitionRequest(string? ActivityId, string? CorrelationId, string? ContextId, object? Input); + public record DispatchWorkflowDefinitionResponse(string WorkflowInstanceId, string? ActivityId); } \ No newline at end of file