From f2d3c540ee06aefe78a03894c1b8c0f97e50113b Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Wed, 17 Sep 2025 14:26:31 +0200 Subject: [PATCH] Add support for asynchronous workflow resumption in Resume endpoint - Introduced `async` parameter to enable asynchronous workflow resumption. - Refactored `ResumeBookmarkedWorkflowAsync` to handle both synchronous and asynchronous resumption via `IWorkflowResumer` and `IBookmarkQueue`. - Updated dependency injection to include `IWorkflowResumer`. --- .../Endpoints/Bookmarks/Resume/Endpoint.cs | 34 ++++++++++++++----- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/src/modules/Elsa.Workflows.Api/Endpoints/Bookmarks/Resume/Endpoint.cs b/src/modules/Elsa.Workflows.Api/Endpoints/Bookmarks/Resume/Endpoint.cs index 95ddfabd8..203a88137 100644 --- a/src/modules/Elsa.Workflows.Api/Endpoints/Bookmarks/Resume/Endpoint.cs +++ b/src/modules/Elsa.Workflows.Api/Endpoints/Bookmarks/Resume/Endpoint.cs @@ -11,7 +11,7 @@ namespace Elsa.Workflows.Api.Endpoints.Bookmarks.Resume; /// Resumes a bookmarked workflow instance with the bookmark ID specified in the provided SAS token. /// [PublicAPI] -internal class Resume(ITokenService tokenService, IBookmarkQueue bookmarkQueue, IPayloadSerializer serializer) : ElsaEndpoint +internal class Resume(ITokenService tokenService, IWorkflowResumer workflowResumer, IBookmarkQueue bookmarkQueue, IPayloadSerializer serializer) : ElsaEndpoint { /// public override void Configure() @@ -25,6 +25,7 @@ internal class Resume(ITokenService tokenService, IBookmarkQueue bookmarkQueue, public override async Task HandleAsync(Request request, CancellationToken cancellationToken) { var token = Query("t")!; + var asynchronous = Query("async", false); if (!tokenService.TryDecryptToken(token, out var payload)) AddError("Invalid token."); @@ -37,7 +38,7 @@ internal class Resume(ITokenService tokenService, IBookmarkQueue bookmarkQueue, return; } - await ResumeBookmarkedWorkflowAsync(payload, input, cancellationToken); + await ResumeBookmarkedWorkflowAsync(payload, input, asynchronous, cancellationToken); if (!HttpContext.Response.HasStarted) await SendOkAsync(cancellationToken); @@ -60,20 +61,35 @@ internal class Resume(ITokenService tokenService, IBookmarkQueue bookmarkQueue, } } - private async Task ResumeBookmarkedWorkflowAsync(BookmarkTokenPayload tokenPayload, IDictionary? input, CancellationToken cancellationToken) + private async Task ResumeBookmarkedWorkflowAsync(BookmarkTokenPayload tokenPayload, IDictionary? input, bool asynchronous, CancellationToken cancellationToken) { var bookmarkId = tokenPayload.BookmarkId; var workflowInstanceId = tokenPayload.WorkflowInstanceId; - var item = new NewBookmarkQueueItem + + if (asynchronous) + { + var item = new NewBookmarkQueueItem + { + BookmarkId = bookmarkId, + WorkflowInstanceId = workflowInstanceId, + Options = new() + { + Input = input + } + }; + + await bookmarkQueue.EnqueueAsync(item, cancellationToken); + return; + } + + var resumeRequest = new ResumeBookmarkRequest { BookmarkId = bookmarkId, WorkflowInstanceId = workflowInstanceId, - Options = new() - { - Input = input - } + Input = input }; - await bookmarkQueue.EnqueueAsync(item, cancellationToken); + + await workflowResumer.ResumeAsync(resumeRequest, cancellationToken); } }