< Summary

Information
Class: Elsa.Workflows.Api.Endpoints.Bookmarks.Resume.Resume
Assembly: Elsa.Workflows.Api
File(s): /home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Workflows.Api/Endpoints/Bookmarks/Resume/Endpoint.cs
Line coverage
10%
Covered lines: 5
Uncovered lines: 43
Coverable lines: 48
Total lines: 109
Line coverage: 10.4%
Branch coverage
0%
Covered branches: 0
Total branches: 12
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
Configure()100%11100%
HandleAsync()0%7280%
GetInputFromQueryString()0%620%
ResumeBookmarkedWorkflowAsync()0%620%

File(s)

/home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Workflows.Api/Endpoints/Bookmarks/Resume/Endpoint.cs

#LineLine coverage
 1using Elsa.Abstractions;
 2using Elsa.SasTokens.Contracts;
 3using Elsa.Workflows.Runtime;
 4using FastEndpoints;
 5using JetBrains.Annotations;
 6using Microsoft.AspNetCore.Http;
 7
 8namespace Elsa.Workflows.Api.Endpoints.Bookmarks.Resume;
 9
 10/// <summary>
 11/// Resumes a bookmarked workflow instance with the bookmark ID specified in the provided SAS token.
 12/// </summary>
 13[PublicAPI]
 114internal class Resume(ITokenService tokenService, IWorkflowResumer workflowResumer, IBookmarkQueue bookmarkQueue, IPaylo
 15{
 16    /// <inheritdoc />
 17    public override void Configure()
 18    {
 119        Routes("/bookmarks/resume");
 120        Verbs(Http.GET, Http.POST);
 121        AllowAnonymous();
 122    }
 23
 24    /// <inheritdoc />
 25    public override async Task HandleAsync(Request request, CancellationToken cancellationToken)
 26    {
 027        var token = Query<string>("t")!;
 028        var asynchronous = Query<bool>("async", false);
 29
 030        if (!tokenService.TryDecryptToken<BookmarkTokenPayload>(token, out var payload))
 031            AddError("Invalid token.");
 32
 033        var input = HttpContext.Request.Method == HttpMethods.Post ? request.Input : GetInputFromQueryString();
 34
 035        if (ValidationFailed)
 36        {
 037            await Send.ErrorsAsync(cancellation: cancellationToken);
 038            return;
 39        }
 40
 41        // Some clients, like Blazor, may prematurely cancel their request upon navigation away from the page.
 42        // In this case, we don't want to cancel the workflow execution.
 43        // We need to better understand the conditions that cause this.
 044        var workflowCancellationToken = CancellationToken.None;
 045        await ResumeBookmarkedWorkflowAsync(payload, input, asynchronous, workflowCancellationToken);
 46
 047        if (!HttpContext.Response.HasStarted)
 048            await Send.OkAsync(cancellationToken);
 049    }
 50
 51    private IDictionary<string, object>? GetInputFromQueryString()
 52    {
 053        var inputJson = Query<string?>("in", false);
 054        if (string.IsNullOrWhiteSpace(inputJson))
 055            return null;
 56
 57        try
 58        {
 059            return serializer.Deserialize<IDictionary<string, object>>(inputJson);
 60        }
 061        catch
 62        {
 063            AddError("Invalid input format. Expected a valid JSON string.");
 064            return null;
 65        }
 066    }
 67
 68    private async Task ResumeBookmarkedWorkflowAsync(BookmarkTokenPayload tokenPayload, IDictionary<string, object>? inp
 69    {
 070        var bookmarkId = tokenPayload.BookmarkId;
 071        var workflowInstanceId = tokenPayload.WorkflowInstanceId;
 72
 073        if (asynchronous)
 74        {
 075            var item = new NewBookmarkQueueItem
 076            {
 077                BookmarkId = bookmarkId,
 078                WorkflowInstanceId = workflowInstanceId,
 079                Options = new()
 080                {
 081                    Input = input
 082                }
 083            };
 84
 085            await bookmarkQueue.EnqueueAsync(item, cancellationToken);
 086            return;
 87        }
 88
 089        var resumeRequest = new ResumeBookmarkRequest
 090        {
 091            BookmarkId = bookmarkId,
 092            WorkflowInstanceId = workflowInstanceId,
 093            Input = input
 094        };
 95
 096        await workflowResumer.ResumeAsync(resumeRequest, cancellationToken);
 097    }
 98}
 99
 100/// <summary>
 101/// The request model for the Resume endpoint.
 102/// </summary>
 103internal class Request
 104{
 105    /// <summary>
 106    /// The input to provide to the workflow when resuming.
 107    /// </summary>
 108    public IDictionary<string, object>? Input { get; set; }
 109}