< Summary

Information
Class: Elsa.Workflows.Runtime.StimulusSender
Assembly: Elsa.Workflows.Runtime
File(s): /home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Workflows.Runtime/Services/StimulusSender.cs
Line coverage
97%
Covered lines: 77
Uncovered lines: 2
Coverable lines: 79
Total lines: 129
Line coverage: 97.4%
Branch coverage
65%
Covered branches: 29
Total branches: 44
Branch coverage: 65.9%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
SendAsync(...)50%22100%
SendAsync()100%88100%
TriggerNewWorkflowsAsync()64.28%141492.59%
ResumeExistingWorkflowsAsync()55%2020100%

File(s)

/home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Workflows.Runtime/Services/StimulusSender.cs

#LineLine coverage
 1using Elsa.Workflows.Runtime.Filters;
 2using Elsa.Workflows.Runtime.Messages;
 3using Elsa.Workflows.Runtime.Results;
 4using Microsoft.Extensions.Logging;
 5using Open.Linq.AsyncExtensions;
 6
 7namespace Elsa.Workflows.Runtime;
 8
 9/// <inheritdoc />
 7110public class StimulusSender(
 7111    IStimulusHasher stimulusHasher,
 7112    ITriggerBoundWorkflowService triggerBoundWorkflowService,
 7113    IWorkflowResumer workflowResumer,
 7114    IBookmarkQueue bookmarkQueue,
 7115    ITriggerInvoker triggerInvoker,
 7116    ILogger<StimulusSender> logger) : IStimulusSender
 17{
 18    /// <inheritdoc />
 19    public Task<SendStimulusResult> SendAsync(string activityTypeName, object stimulus, StimulusMetadata? metadata = nul
 20    {
 921        var stimulusHash = stimulusHasher.Hash(activityTypeName, stimulus, metadata?.ActivityInstanceId);
 922        return SendAsync(stimulusHash, metadata, cancellationToken);
 23    }
 24
 25    /// <inheritdoc />
 26    public async Task<SendStimulusResult> SendAsync(string stimulusHash, StimulusMetadata? metadata = null, Cancellation
 27    {
 928        var responses = new List<RunWorkflowInstanceResponse>();
 29
 930        if (metadata == null || (metadata.WorkflowInstanceId == null && metadata.BookmarkId == null && metadata.Activity
 31        {
 532            var triggered = await TriggerNewWorkflowsAsync(stimulusHash, metadata, cancellationToken);
 533            responses.AddRange(triggered);
 34        }
 35
 936        var resumed = await ResumeExistingWorkflowsAsync(stimulusHash, metadata, cancellationToken);
 937        responses.AddRange(resumed);
 938        return new(responses);
 939    }
 40
 41    private async Task<ICollection<RunWorkflowInstanceResponse>> TriggerNewWorkflowsAsync(string stimulusHash, StimulusM
 42    {
 543        var triggerBoundWorkflows = await triggerBoundWorkflowService.FindManyAsync(stimulusHash, cancellationToken).ToL
 544        var correlationId = metadata?.CorrelationId;
 545        var input = metadata?.Input;
 546        var properties = metadata?.Properties;
 547        var parentId = metadata?.ParentWorkflowInstanceId;
 548        var responses = new List<RunWorkflowInstanceResponse>();
 49
 2050        foreach (var triggerBoundWorkflow in triggerBoundWorkflows)
 51        {
 552            var workflowGraph = triggerBoundWorkflow.WorkflowGraph;
 553            var workflow = workflowGraph.Workflow;
 54
 2055            foreach (var trigger in triggerBoundWorkflow.Triggers)
 56            {
 557                var triggerRequest = new InvokeTriggerRequest
 558                {
 559                    CorrelationId = correlationId,
 560                    Workflow = workflow,
 561                    ActivityId = trigger.ActivityId,
 562                    Input = input,
 563                    Properties = properties,
 564                    ParentWorkflowInstanceId = parentId
 565                };
 66
 567                var response = await triggerInvoker.InvokeAsync(triggerRequest, cancellationToken);
 68
 569                if (response.CannotStart)
 70                {
 071                    logger.LogWarning("Workflow activation strategy disallowed starting workflow {WorkflowDefinitionHand
 072                    continue;
 73                }
 74
 575                responses.Add(response.ToRunWorkflowInstanceResponse());
 76            }
 577        }
 78
 579        return responses;
 580    }
 81
 82    private async Task<ICollection<RunWorkflowInstanceResponse>> ResumeExistingWorkflowsAsync(string stimulusHash, Stimu
 83    {
 984        var input = metadata?.Input;
 985        var properties = metadata?.Properties;
 86
 987        var bookmarkFilter = new BookmarkFilter
 988        {
 989            Hash = stimulusHash,
 990            CorrelationId = metadata?.CorrelationId,
 991            WorkflowInstanceId = metadata?.WorkflowInstanceId,
 992            ActivityInstanceId = metadata?.ActivityInstanceId,
 993            BookmarkId = metadata?.BookmarkId
 994        };
 995        var responses = (await workflowResumer.ResumeAsync(bookmarkFilter, new()
 996        {
 997            Input = input,
 998            Properties = properties
 999        }, cancellationToken)).ToList();
 100
 9101        if (responses.Count > 0)
 102        {
 2103            logger.LogDebug("Successfully resumed {WorkflowCount} workflow instances using stimulus {StimulusHash}", res
 2104            return responses;
 105        }
 106
 107        // If no bookmarks were matched, enqueue the request in case a matching bookmark is created in the near future.
 7108        var workflowInstanceId = metadata?.WorkflowInstanceId;
 109
 7110        var bookmarkQueueItem = new NewBookmarkQueueItem
 7111        {
 7112            WorkflowInstanceId = workflowInstanceId,
 7113            BookmarkId = metadata?.BookmarkId,
 7114            CorrelationId = metadata?.CorrelationId,
 7115            StimulusHash = stimulusHash,
 7116            Options = new()
 7117            {
 7118                Input = input,
 7119                Properties = properties
 7120            }
 7121        };
 122
 7123        logger.LogDebug("Bookmark queue item enqueued with stimulus: {StimulusHash}", bookmarkQueueItem.StimulusHash);
 124
 7125        await bookmarkQueue.EnqueueAsync(bookmarkQueueItem, cancellationToken);
 126
 7127        return responses;
 9128    }
 129}