< Summary

Information
Class: Elsa.Workflows.Runtime.BackgroundActivityInvoker
Assembly: Elsa.Workflows.Runtime
File(s): /home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Workflows.Runtime/Services/BackgroundActivityInvoker.cs
Line coverage
97%
Covered lines: 65
Uncovered lines: 2
Coverable lines: 67
Total lines: 95
Line coverage: 97%
Branch coverage
58%
Covered branches: 7
Total branches: 12
Branch coverage: 58.3%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
ExecuteAsync()50%44100%
ResumeWorkflowAsync()62.5%8894.87%

File(s)

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

#LineLine coverage
 1using System.Text.Json;
 2using Elsa.Workflows.Management;
 3using Elsa.Workflows.Runtime.Middleware.Activities;
 4using Elsa.Workflows.Runtime.Options;
 5using Microsoft.Extensions.Logging;
 6
 7namespace Elsa.Workflows.Runtime;
 8
 9/// <summary>
 10/// An activity invoker that invokes activities detached from the workflow. This is useful for invoking activities from 
 11/// </summary>
 312public class BackgroundActivityInvoker(
 313    IBookmarkQueue bookmarkQueue,
 314    IWorkflowInstanceManager workflowInstanceManager,
 315    IWorkflowDefinitionService workflowDefinitionService,
 316    IVariablePersistenceManager variablePersistenceManager,
 317    IActivityInvoker activityInvoker,
 318    IActivityPropertyLogPersistenceEvaluator activityPropertyLogPersistenceEvaluator,
 319    WorkflowHeartbeatGeneratorFactory workflowHeartbeatGeneratorFactory,
 320    IServiceProvider serviceProvider,
 321    ILogger<BackgroundActivityInvoker> logger)
 22    : IBackgroundActivityInvoker
 23{
 324    private readonly ILogger _logger = logger;
 25
 26    /// <inheritdoc />
 27    public async Task ExecuteAsync(ScheduledBackgroundActivity scheduledBackgroundActivity, CancellationToken cancellati
 28    {
 329        var workflowInstanceId = scheduledBackgroundActivity.WorkflowInstanceId;
 330        var workflowInstance = await workflowInstanceManager.FindByIdAsync(workflowInstanceId, cancellationToken);
 331        if (workflowInstance == null) throw new("Workflow instance not found");
 332        var workflowState = workflowInstance.WorkflowState;
 333        var workflow = await workflowDefinitionService.FindWorkflowGraphAsync(workflowInstance.DefinitionVersionId, canc
 334        if (workflow == null) throw new("Workflow definition not found");
 335        var workflowExecutionContext = await WorkflowExecutionContext.CreateAsync(serviceProvider, workflow, workflowSta
 336        var activityNodeId = scheduledBackgroundActivity.ActivityNodeId;
 737        var activityExecutionContext = workflowExecutionContext.ActivityExecutionContexts.First(x => x.NodeId == activit
 38
 339        using (workflowHeartbeatGeneratorFactory.CreateHeartbeatGenerator(workflowExecutionContext))
 40        {
 341            await variablePersistenceManager.LoadVariablesAsync(workflowExecutionContext);
 342            activityExecutionContext.SetIsBackgroundExecution();
 343            await activityInvoker.InvokeAsync(activityExecutionContext);
 344            await variablePersistenceManager.SaveVariablesAsync(workflowExecutionContext);
 345        }
 346        await ResumeWorkflowAsync(activityExecutionContext, scheduledBackgroundActivity);
 347    }
 48
 49    private async Task ResumeWorkflowAsync(ActivityExecutionContext activityExecutionContext, ScheduledBackgroundActivit
 50    {
 351        var cancellationToken = activityExecutionContext.CancellationToken;
 352        var activityNodeId = scheduledBackgroundActivity.ActivityNodeId;
 353        if (cancellationToken.IsCancellationRequested)
 54        {
 055            _logger.LogInformation("Background execution for activity {ActivityNodeId} was canceled", activityNodeId);
 056            return;
 57        }
 58
 359        var inputKey = BackgroundActivityInvokerMiddleware.GetBackgroundActivityOutputKey(activityNodeId);
 360        var outcomesKey = BackgroundActivityInvokerMiddleware.GetBackgroundActivityOutcomesKey(activityNodeId);
 361        var completedKey = BackgroundActivityInvokerMiddleware.GetBackgroundActivityCompletedKey(activityNodeId);
 362        var journalDataKey = BackgroundActivityInvokerMiddleware.GetBackgroundActivityJournalDataKey(activityNodeId);
 363        var bookmarksKey = BackgroundActivityInvokerMiddleware.GetBackgroundActivityBookmarksKey(activityNodeId);
 364        var scheduledActivitiesKey = BackgroundActivityInvokerMiddleware.GetBackgroundActivityScheduledActivitiesKey(act
 365        var propsKey = BackgroundActivityInvokerMiddleware.GetBackgroundActivityPropertiesKey(activityNodeId);
 366        var outcomes = activityExecutionContext.GetBackgroundOutcomes()?.ToList();
 367        var completed = activityExecutionContext.GetBackgroundCompleted();
 368        var scheduledActivities = activityExecutionContext.GetBackgroundScheduledActivities().ToList();
 369        var workflowInstanceId = scheduledBackgroundActivity.WorkflowInstanceId;
 370        var outputValues = await activityPropertyLogPersistenceEvaluator.GetPersistableOutputAsync(activityExecutionCont
 371        var bookmarkProps = new Dictionary<string, object>
 372        {
 373            [scheduledActivitiesKey] = JsonSerializer.Serialize(scheduledActivities),
 374            [inputKey] = outputValues,
 375            [journalDataKey] = activityExecutionContext.JournalData,
 376            [bookmarksKey] = activityExecutionContext.Bookmarks.ToList(),
 377            [propsKey] = activityExecutionContext.Properties.ToDictionary() // ChangeTrackingDictionary is not persistab
 378        };
 79
 380        if (outcomes != null) bookmarkProps[outcomesKey] = outcomes;
 681        if (completed != null) bookmarkProps[completedKey] = completed;
 82
 383        var resumeBookmarkOptions = new ResumeBookmarkOptions
 384        {
 385            Properties = bookmarkProps,
 386        };
 387        var enqueuedBookmark = new NewBookmarkQueueItem
 388        {
 389            WorkflowInstanceId = workflowInstanceId,
 390            BookmarkId = scheduledBackgroundActivity.BookmarkId,
 391            Options = resumeBookmarkOptions
 392        };
 393        await bookmarkQueue.EnqueueAsync(enqueuedBookmark, cancellationToken);
 394    }
 95}