< Summary

Line coverage
83%
Covered lines: 251
Uncovered lines: 51
Coverable lines: 302
Total lines: 951
Line coverage: 83.1%
Branch coverage
82%
Covered branches: 87
Total branches: 106
Branch coverage: 82%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
File 1: CanCancelActivity()50%22100%
File 1: CancelActivityAsync()50%2290%
File 1: CancelChildActivitiesAsync()50%2266.66%
File 2: CompleteActivityAsync()75%131281.81%
File 2: CompleteActivityWithOutcomesAsync(...)100%11100%
File 2: CompleteCompositeAsync()100%210%
File 3: .ctor(...)100%44100%
File 3: get_Id()100%11100%
File 3: get_StartedAt()100%11100%
File 3: get_Tag()100%11100%
File 3: get_CompletedAt()100%11100%
File 3: get_IsCompleted()100%22100%
File 3: get_IsExecuting()100%11100%
File 3: get_AggregateFaultCount()100%11100%
File 3: get_WorkflowExecutionContext()100%11100%
File 3: get_ParentActivityExecutionContext()100%11100%
File 3: set_ParentActivityExecutionContext(...)100%22100%
File 3: get_ExpressionExecutionContext()100%11100%
File 3: get_Variables()83.33%1212100%
File 3: get_DynamicVariables()100%11100%
File 3: get_Activity()100%11100%
File 3: get_ActivityDescriptor()100%11100%
File 3: get_CancellationToken()100%11100%
File 3: get_Status()100%11100%
File 3: set_Status(...)100%22100%
File 3: EnterExecution()100%11100%
File 3: TransitionTo(...)100%11100%
File 3: get_Exception()100%11100%
File 3: set_Exception(...)100%11100%
File 3: get_Properties()100%11100%
File 3: get_TransientProperties()100%11100%
File 3: get_Metadata()100%11100%
File 3: get_ActivityNode()100%11100%
File 3: get_NodeId()100%11100%
File 3: get_Children()100%11100%
File 3: get_Bookmarks()100%11100%
File 3: get_NewBookmarks()100%11100%
File 3: get_ExecutionCount()100%210%
File 3: get_WorkflowInput()100%11100%
File 3: get_ActivityInput()100%11100%
File 3: get_JournalData()100%11100%
File 3: get_ActivityState()100%11100%
File 3: get_IsDirty()100%11100%
File 3: ScheduleActivityAsync(...)100%22100%
File 3: ScheduleActivityAsync()100%11100%
File 3: ScheduleActivityAsync()100%11100%
File 3: ScheduleActivityAsync()100%210%
File 3: ScheduleActivitiesAsync()100%210%
File 3: ScheduleActivities(...)50%22100%
File 3: ScheduleActivities()100%22100%
File 3: CreateBookmarks(...)100%22100%
File 3: AddBookmarks(...)100%210%
File 3: AddBookmark(...)100%11100%
File 3: CreateBookmark(...)100%210%
File 3: CreateBookmark(...)100%210%
File 3: CreateBookmark(...)100%210%
File 3: CreateBookmark(...)100%11100%
File 3: CreateBookmark(...)100%2424100%
File 3: ClearBookmarks()100%11100%
File 3: GetProperty(...)100%22100%
File 3: GetProperty(...)100%22100%
File 3: SetProperty(...)100%11100%
File 3: UpdateProperty(...)100%11100%
File 3: RemoveProperty(...)100%210%
File 3: GetMetadata(...)0%620%
File 3: GetMetadata(...)100%22100%
File 3: SetMetadata(...)100%11100%
File 3: UpdateMetadata(...)100%210%
File 3: RemoveMetadata(...)100%210%
File 3: GetRequiredService()100%11100%
File 3: GetRequiredService(...)100%11100%
File 3: GetOrCreateService()100%210%
File 3: GetOrCreateService(...)100%210%
File 3: GetService()100%11100%
File 3: GetServices()100%11100%
File 3: GetService(...)100%210%
File 3: Get(...)100%22100%
File 3: Get(...)0%620%
File 3: Get(...)100%22100%
File 3: Get(...)50%22100%
File 3: Get(...)100%22100%
File 3: TryGet(...)25%7444.44%
File 3: Set(...)100%11100%
File 3: Set(...)100%11100%
File 3: Set(...)100%11100%
File 3: ClearCompletionCallbacks()100%11100%
File 3: Taint()100%22100%
File 3: ClearTaint()100%22100%
File 3: IncrementExecutionCount()100%11100%
File 3: GetMemoryBlock(...)50%22100%
File 3: System.IDisposable.Dispose()100%210%
File 4: AddExecutionLogEntry(...)100%44100%

File(s)

/home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Workflows.Core/Contexts/ActivityExecutionContext.Cancel.cs

#LineLine coverage
 1using Elsa.Extensions;
 2using Elsa.Mediator.Contracts;
 3using Elsa.Workflows.Notifications;
 4using Elsa.Workflows.Signals;
 5
 6namespace Elsa.Workflows;
 7
 8public partial class ActivityExecutionContext
 9{
 10    private readonly INotificationSender _publisher;
 11
 12    private bool CanCancelActivity()
 13    {
 269214        return Status is not ActivityStatus.Canceled and not ActivityStatus.Completed;
 15    }
 16
 17    private async Task CancelActivityAsync()
 18    {
 419        if(!CanCancelActivity())
 020            return;
 21
 422        TransitionTo(ActivityStatus.Canceled);
 423        ClearBookmarks();
 424        ClearCompletionCallbacks();
 925        WorkflowExecutionContext.Bookmarks.RemoveWhere(x => x.ActivityNodeId == NodeId);
 426        AddExecutionLogEntry("Canceled");
 427        await this.SendSignalAsync(new CancelSignal());
 428        await CancelChildActivitiesAsync();
 29
 30        // ReSharper disable once MethodSupportsCancellation
 431        await _publisher.SendAsync(new ActivityCancelled(this));
 432    }
 33
 34    private async Task CancelChildActivitiesAsync()
 35    {
 2636        var childContexts = WorkflowExecutionContext.ActivityExecutionContexts.Where(x => x.ParentActivityExecutionConte
 37
 838        foreach (var childContext in childContexts)
 039            await childContext.CancelActivityAsync();
 440    }
 41}

/home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Workflows.Core/Contexts/ActivityExecutionContext.Complete.cs

#LineLine coverage
 1using Elsa.Extensions;
 2using Elsa.Mediator.Contracts;
 3using Elsa.Workflows.Activities.Flowchart.Models;
 4using Elsa.Workflows.Signals;
 5
 6namespace Elsa.Workflows;
 7
 8public partial class ActivityExecutionContext
 9{
 10    /// <summary>
 11    /// Complete the current activity. This should only be called by activities that explicitly suppress automatic-compl
 12    /// </summary>
 13    public async ValueTask CompleteActivityAsync(object? result = null)
 14    {
 340715        var outcomes = result as Outcomes;
 16
 17        // If the activity is executing in the background, simply capture the result and return.
 340718        if (this.GetIsBackgroundExecution())
 19        {
 020            if (outcomes != null)
 021                this.SetBackgroundOutcomes(outcomes.Names);
 22            else
 023                this.SetBackgroundCompletion();
 024            return;
 25        }
 26
 27        // If the activity is not running, do nothing.
 340728        if (Status != ActivityStatus.Running)
 729            return;
 30
 31        // Cancel any non-completed child activities.
 608832        var childContexts = Children.Where(x => x.CanCancelActivity()).ToList();
 33
 680834        foreach (var childContext in childContexts)
 435            await childContext.CancelActivityAsync();
 36
 37        // Mark the activity as complete.
 340038        TransitionTo(ActivityStatus.Completed);
 39
 40        // Record the outcomes, if any.
 340041        if (outcomes != null)
 10442            JournalData["Outcomes"] = outcomes.Names;
 43
 44        // Add an execution log entry.
 340045        AddExecutionLogEntry("Completed");
 46
 47        // Send a signal.
 340048        await this.SendSignalAsync(new ActivityCompleted(result));
 49
 50        // Clear bookmarks.
 340051        ClearBookmarks();
 343352        WorkflowExecutionContext.Bookmarks.RemoveWhere(x => x.ActivityInstanceId == Id);
 53
 54        // Remove completion callbacks.
 340055        ClearCompletionCallbacks();
 56
 57        // Remove all associated variables, unless this is the root context - in which case we want to keep the variable
 340058        if (ParentActivityExecutionContext != null)
 59        {
 275160            var variablePersistenceManager = GetRequiredService<IVariablePersistenceManager>();
 275161            await variablePersistenceManager.DeleteVariablesAsync(this);
 62        }
 63
 64        // Update the completed at timestamp.
 340065        CompletedAt = WorkflowExecutionContext.SystemClock.UtcNow;
 340766    }
 67
 68    /// <summary>
 69    /// Complete the current activity with the specified outcomes.
 70    /// </summary>
 71    public ValueTask CompleteActivityWithOutcomesAsync(params string[] outcomes)
 72    {
 9973        return CompleteActivityAsync(new Outcomes(outcomes));
 74    }
 75
 76    /// <summary>
 77    /// Complete the current composite activity with the specified outcome.
 78    /// </summary>
 79    public async ValueTask CompleteCompositeAsync(params string[] outcomes)
 80    {
 081        await this.SendSignalAsync(new CompleteCompositeSignal(new Outcomes(outcomes)));
 082    }
 83}

/home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Workflows.Core/Contexts/ActivityExecutionContext.cs

#LineLine coverage
 1using System.Runtime.CompilerServices;
 2using Elsa.Common;
 3using Elsa.Expressions.Helpers;
 4using Elsa.Expressions.Models;
 5using Elsa.Extensions;
 6using Elsa.Mediator.Contracts;
 7using Elsa.Workflows.Memory;
 8using Elsa.Workflows.Models;
 9using Elsa.Workflows.Options;
 10using JetBrains.Annotations;
 11
 12namespace Elsa.Workflows;
 13
 14/// <summary>
 15/// Represents the context of an activity execution.
 16/// </summary>
 17[PublicAPI]
 18public partial class ActivityExecutionContext : IExecutionContext, IDisposable
 19{
 20    private readonly ISystemClock _systemClock;
 21    private ActivityStatus _status;
 22    private Exception? _exception;
 23    private long _executionCount;
 24    private ActivityExecutionContext? _parentActivityExecutionContext;
 25
 26    // Bookmarks created during the lifetime of this activity.
 387727    private List<Bookmark> _newBookmarks = [];
 28
 29    /// <summary>
 30    /// Initializes a new instance of the <see cref="ActivityExecutionContext"/> class.
 31    /// </summary>
 387732    public ActivityExecutionContext(
 387733        string id,
 387734        WorkflowExecutionContext workflowExecutionContext,
 387735        ActivityExecutionContext? parentActivityExecutionContext,
 387736        IActivity activity,
 387737        ActivityDescriptor activityDescriptor,
 387738        DateTimeOffset startedAt,
 387739        object? tag,
 387740        ISystemClock systemClock,
 387741        CancellationToken cancellationToken)
 42    {
 387743        _systemClock = systemClock;
 387744        Properties = new ChangeTrackingDictionary<string, object>(Taint);
 387745        Metadata = new ChangeTrackingDictionary<string, object>(Taint);
 387746        ActivityState = new ChangeTrackingDictionary<string, object>(Taint);
 387747        ActivityInput = new ChangeTrackingDictionary<string, object>(Taint);
 387748        WorkflowExecutionContext = workflowExecutionContext;
 387749        ParentActivityExecutionContext = parentActivityExecutionContext;
 387750        var expressionExecutionContextProps = ExpressionExecutionContextExtensions.CreateActivityExecutionContextPropert
 387751        expressionExecutionContextProps[ExpressionExecutionContextExtensions.ActivityKey] = activity;
 387752        ExpressionExecutionContext = new(workflowExecutionContext.ServiceProvider, new(), parentActivityExecutionContext
 387753        Activity = activity;
 387754        ActivityDescriptor = activityDescriptor;
 387755        StartedAt = startedAt;
 387756        Status = ActivityStatus.Pending;
 387757        Tag = tag;
 387758        CancellationToken = cancellationToken;
 387759        Id = id;
 387760        _publisher = GetRequiredService<INotificationSender>();
 387761    }
 62
 63    /// <summary>
 64    /// The ID of the current activity execution context.
 65    /// </summary>
 3178166    public string Id { get; set; }
 67
 68    /// <summary>
 69    /// The time at which the activity execution context was created.
 70    /// </summary>
 813971    public DateTimeOffset StartedAt { get; set; }
 72
 73    /// <summary>
 74    /// An optional tag to associate with the activity execution.
 75    /// </summary>
 746476    public object? Tag { get; set; }
 77
 78    /// <summary>
 79    /// The time at which the activity execution context was completed.
 80    /// </summary>
 766281    public DateTimeOffset? CompletedAt { get; set; }
 82
 83    /// <summary>
 84    /// Returns true if the activity execution context has completed.
 85    /// </summary>
 1346886    public bool IsCompleted => Status is ActivityStatus.Completed or ActivityStatus.Canceled;
 87
 88    /// <summary>
 89    /// Gets or sets a value indicating whether the activity is actively executing.
 90    /// </summary>
 91    /// <remarks>
 92    /// This flag is set to <c>true</c> immediately before the activity begins execution
 93    /// and is set to <c>false</c> once the execution is completed.
 94    /// It can be used to determine if an activity was in-progress in case of unexpected
 95    /// application termination, allowing the system to retry execution upon restarting.
 96    /// </remarks>
 745197    public bool IsExecuting { get; set; }
 98
 99    /// <summary>
 100    /// The number of faults encountered during the execution of the activity and its descendants.
 101    /// </summary>
 4355102    public int AggregateFaultCount { get; set; }
 103
 104    /// <summary>
 105    /// The workflow execution context.
 106    /// </summary>
 168720107    public WorkflowExecutionContext WorkflowExecutionContext { get; }
 108
 109    /// <summary>
 110    /// The parent activity execution context, if any.
 111    /// </summary>
 112    public ActivityExecutionContext? ParentActivityExecutionContext
 113    {
 62132114        get => _parentActivityExecutionContext;
 115        internal set
 116        {
 3982117            _parentActivityExecutionContext = value;
 3982118            _parentActivityExecutionContext?.Children.Add(this);
 2912119        }
 120    }
 121
 122    /// <summary>
 123    /// The expression execution context.
 124    /// </summary>
 45637125    public ExpressionExecutionContext ExpressionExecutionContext { get; }
 126
 127    /// <inheritdoc />
 128    public IEnumerable<Variable> Variables
 129    {
 130        get
 131        {
 6395132            var containerVariables = (Activity as IVariableContainer)?.Variables ?? Enumerable.Empty<Variable>();
 6395133            var dynamicVariables = DynamicVariables;
 6395134            var mergedVariables = new Dictionary<string, Variable>();
 135
 13068136            foreach (var containerVariable in containerVariables)
 137            {
 139138                var name = !string.IsNullOrEmpty(containerVariable.Name) ? containerVariable.Name : containerVariable.Id
 139139                mergedVariables[name] = containerVariable;
 140            }
 141
 13160142            foreach (var dynamicVariable in dynamicVariables)
 143            {
 185144                var name = !string.IsNullOrEmpty(dynamicVariable.Name) ? dynamicVariable.Name : dynamicVariable.Id;
 185145                mergedVariables[name] = dynamicVariable;
 146            }
 6395147            return mergedVariables.Values;
 148        }
 149    }
 150
 151    /// <summary>
 152    /// A list of variables that are dynamically added to the activity execution context.
 153    /// </summary>
 11265154    public ICollection<Variable> DynamicVariables { get; set; } = new List<Variable>();
 155
 156    /// <summary>
 157    /// The currently executing activity.
 158    /// </summary>
 200754159    public IActivity Activity { get; set; }
 160
 161    /// <summary>
 162    /// The activity descriptor.
 163    /// </summary>
 26033164    public ActivityDescriptor ActivityDescriptor { get; }
 165
 166    /// <summary>
 167    /// A cancellation token to use when invoking asynchronous operations.
 168    /// </summary>
 34426169    public CancellationToken CancellationToken { get; }
 170
 171    /// <summary>
 172    /// The current status of the activity.
 173    /// </summary>
 174    public ActivityStatus Status
 175    {
 40254176        get => _status;
 177        private set
 178        {
 11145179            if (value == _status)
 3916180                return;
 181
 7229182            _status = value;
 7229183            Taint();
 7229184        }
 185    }
 186
 187    public IDisposable EnterExecution()
 188    {
 3316189        return new WorkflowExecutionState(this);
 190    }
 191
 192    /// <summary>
 193    /// Sets the current status of the activity.
 194    /// </summary>
 195    public void TransitionTo(ActivityStatus status)
 196    {
 7268197        Status = status;
 7268198    }
 199
 200    /// <summary>
 201    /// Gets or sets the exception that occurred during the activity execution, if any.
 202    /// </summary>
 203    public Exception? Exception
 204    {
 3444205        get => _exception;
 206        set
 207        {
 16208            _exception = value;
 16209            Taint();
 16210        }
 211    }
 212
 213    /// <inheritdoc />
 12890214    public IDictionary<string, object> Properties { get; private set; }
 215
 216    /// <summary>
 217    /// A transient dictionary of values that can be associated with this activity execution context.
 218    /// These properties only exist while the activity executes and are not persisted.
 219    /// </summary>
 44565220    public IDictionary<object, object> TransientProperties { get; set; } = new Dictionary<object, object>();
 221
 222    /// <summary>
 223    /// A dictionary of metadata about this execution. In contrast to <see cref="Properties"/>, this metadata is never p
 224    /// </summary>
 8199225    public IDictionary<string, object> Metadata { get; private set; }
 226
 227    /// <summary>
 228    /// Returns the <see cref="ActivityNode"/> metadata about the current activity.
 229    /// </summary>
 31912230    public ActivityNode ActivityNode => WorkflowExecutionContext.FindNodeByActivity(Activity)!;
 231
 232    /// <summary>
 233    /// Returns the global node ID for the current activity within the graph.
 234    /// </summary>
 235    /// <remarks>As of tool version 3.0, all activity IDs are already unique, so there's no need to construct a hierarch
 11154236    public string NodeId => ActivityNode.NodeId;
 237
 14652238    public ISet<ActivityExecutionContext> Children { get; } = new HashSet<ActivityExecutionContext>();
 239
 240    /// <summary>
 241    /// A list of bookmarks associated with the current activity.
 242    /// </summary>
 3632243    public IEnumerable<Bookmark> Bookmarks => WorkflowExecutionContext.Bookmarks.Where(x => x.ActivityInstanceId == Id);
 244
 245    /// <summary>
 246    /// A collection of bookmarks created during the execution of the activity.
 247    /// </summary>
 681248    public IEnumerable<Bookmark> NewBookmarks => _newBookmarks.AsReadOnly();
 249
 250    /// <summary>
 251    /// The number of times this <see cref="ActivityExecutionContext"/> has executed.
 252    /// </summary>
 0253    public long ExecutionCount => _executionCount;
 254
 255    /// <summary>
 256    /// A dictionary of received inputs for the current workflow.
 257    /// </summary>
 297258    public IDictionary<string, object> WorkflowInput => WorkflowExecutionContext.Input;
 259
 260    /// <summary>
 261    /// A dictionary of inputs for the current activity.
 262    /// </summary>
 7883263    public IDictionary<string, object> ActivityInput { get; private set; }
 264
 265    /// <summary>
 266    /// Journal data will be added to the workflow execution log for the "Executed" event.
 267    /// </summary>
 268    // ReSharper disable once CollectionNeverQueried.Global
 7464269    public IDictionary<string, object> JournalData { get; } = new Dictionary<string, object>();
 270
 271    /// <summary>
 272    /// Stores the evaluated inputs, serialized, for the current activity for historical purposes.
 273    /// </summary>
 10545274    public IDictionary<string, object> ActivityState { get; }
 275
 276    /// <summary>
 277    /// Indicates whether the state of the current activity execution context has been modified.
 278    /// </summary>
 31368279    public bool IsDirty { get; private set; }
 280
 281    /// <summary>
 282    /// Schedules the specified activity to be executed.
 283    /// </summary>
 284    /// <param name="activity">The activity to schedule.</param>
 285    /// <param name="completionCallback">An optional callback to invoke when the activity completes.</param>
 286    /// <param name="tag">An optional tag to associate with the activity execution.</param>
 287    /// <param name="variables">An optional list of variables to declare with the activity execution.</param>
 288    public ValueTask ScheduleActivityAsync(IActivity? activity, ActivityCompletionCallback? completionCallback, object? 
 289    {
 2941290        var options = new ScheduleWorkOptions
 2941291        {
 2941292            CompletionCallback = completionCallback,
 2941293            Tag = tag,
 2941294            Variables = variables?.ToList()
 2941295        };
 2941296        return ScheduleActivityAsync(activity, options);
 297    }
 298
 299    /// <summary>
 300    /// Schedules the specified activity to be executed.
 301    /// </summary>
 302    /// <param name="activity">The activity to schedule.</param>
 303    /// <param name="options">The options used to schedule the activity.</param>
 304    public async ValueTask ScheduleActivityAsync(IActivity? activity, ScheduleWorkOptions? options = null)
 305    {
 2960306        await ScheduleActivityAsync(activity, this, options);
 2960307    }
 308
 309    /// <summary>
 310    /// Schedules the specified activity to be executed.
 311    /// </summary>
 312    /// <param name="activity">The activity to schedule.</param>
 313    /// <param name="owner">The activity execution context that owns the scheduled activity.</param>
 314    /// <param name="options">The options used to schedule the activity.</param>
 315    public async ValueTask ScheduleActivityAsync(IActivity? activity, ActivityExecutionContext? owner, ScheduleWorkOptio
 316    {
 2960317        var schedulerStrategy = GetRequiredService<IActivityExecutionContextSchedulerStrategy>();
 2960318        await schedulerStrategy.ScheduleActivityAsync(this, activity, owner, options);
 2960319    }
 320
 321    /// <summary>
 322    /// Schedules the specified activity to be executed.
 323    /// </summary>
 324    /// <param name="activityNode">The activity node to schedule.</param>
 325    /// <param name="owner">The activity execution context that owns the scheduled activity.</param>
 326    /// <param name="options">The options used to schedule the activity.</param>
 327    public async Task ScheduleActivityAsync(ActivityNode? activityNode, ActivityExecutionContext? owner = null, Schedule
 328    {
 0329        var schedulerStrategy = GetRequiredService<IActivityExecutionContextSchedulerStrategy>();
 0330        await schedulerStrategy.ScheduleActivityAsync(this, activityNode, owner, options);
 0331    }
 332
 333    /// <summary>
 334    /// Schedules the specified activities to be executed.
 335    /// </summary>
 336    /// <param name="activities">The activities to schedule.</param>
 0337    public async ValueTask ScheduleActivitiesAsync(params IActivity?[] activities) => await ScheduleActivities(activitie
 338
 339    /// <summary>
 340    /// Schedules the specified activities to be executed.
 341    /// </summary>
 342    /// <param name="activities">The activities to schedule.</param>
 343    /// <param name="completionCallback">The callback to invoke when the activities complete.</param>
 344    /// <param name="tag">An optional tag to associate with the activity execution.</param>
 345    /// <param name="variables">An optional list of variables to declare with the activity execution.</param>
 346    public ValueTask ScheduleActivities(IEnumerable<IActivity?> activities, ActivityCompletionCallback? completionCallba
 347    {
 7348        var options = new ScheduleWorkOptions
 7349        {
 7350            CompletionCallback = completionCallback,
 7351            Tag = tag,
 7352            Variables = variables?.ToList()
 7353        };
 7354        return ScheduleActivities(activities, options);
 355    }
 356
 357    /// <summary>
 358    /// Schedules the specified activities to be executed.
 359    /// </summary>
 360    /// <param name="activities">The activities to schedule.</param>
 361    /// <param name="options">The options used to schedule the activities.</param>
 362    public async ValueTask ScheduleActivities(IEnumerable<IActivity?> activities, ScheduleWorkOptions? options = null)
 363    {
 42364        foreach (var activity in activities)
 14365            await ScheduleActivityAsync(activity, options);
 7366    }
 367
 368    /// <summary>
 369    /// Creates a bookmark for each payload.
 370    /// </summary>
 371    /// <param name="payloads">The payloads to create bookmarks for.</param>
 372    /// <param name="callback">An optional callback that is invoked when the bookmark is resumed.</param>
 373    /// <param name="includeActivityInstanceId">Whether or not the activity instance ID should be included in the bookma
 374    /// <param name="bookmarkName">An optional name to use for the bookmark. Defaults to the activity type.</param>
 375    public void CreateBookmarks(IEnumerable<object> payloads, ExecuteActivityDelegate? callback = null, bool includeActi
 376    {
 28377        foreach (var payload in payloads)
 7378            CreateBookmark(new()
 7379            {
 7380                Stimulus = payload,
 7381                Callback = callback,
 7382                BookmarkName = bookmarkName,
 7383                IncludeActivityInstanceId = includeActivityInstanceId
 7384            });
 7385    }
 386
 387    /// <summary>
 388    /// Adds each bookmark to the list of bookmarks.
 389    /// </summary>
 390    /// <param name="bookmarks">The bookmarks to add.</param>
 391    public void AddBookmarks(IEnumerable<Bookmark> bookmarks)
 392    {
 0393        WorkflowExecutionContext.Bookmarks.AddRange(bookmarks);
 0394        Taint();
 0395    }
 396
 397    /// <summary>
 398    /// Adds a bookmark to the list of bookmarks.
 399    /// </summary>
 400    /// <param name="bookmark">The bookmark to add.</param>
 401    public void AddBookmark(Bookmark bookmark)
 402    {
 73403        _newBookmarks.Add(bookmark);
 73404        WorkflowExecutionContext.Bookmarks.Add(bookmark);
 73405        Taint();
 73406    }
 407
 408    /// <summary>
 409    /// Creates a bookmark so that this activity can be resumed at a later time.
 410    /// </summary>
 411    /// <param name="callback">An optional callback that is invoked when the bookmark is resumed.</param>
 412    /// <param name="metadata">Custom properties to associate with the bookmark.</param>
 413    /// <returns>The created bookmark.</returns>
 414    public Bookmark CreateBookmark(ExecuteActivityDelegate callback, IDictionary<string, string>? metadata = null)
 415    {
 0416        return CreateBookmark(new()
 0417        {
 0418            Callback = callback,
 0419            Metadata = metadata
 0420        });
 421    }
 422
 423    /// <summary>
 424    /// Creates a bookmark so that this activity can be resumed at a later time.
 425    /// </summary>
 426    /// <param name="stimulus">The payload to associate with the bookmark.</param>
 427    /// <param name="callback">An optional callback that is invoked when the bookmark is resumed.</param>
 428    /// <param name="includeActivityInstanceId">Whether or not the activity instance ID should be included in the bookma
 429    /// <param name="customProperties">Custom properties to associate with the bookmark.</param>
 430    /// <returns>The created bookmark.</returns>
 431    public Bookmark CreateBookmark(object stimulus, ExecuteActivityDelegate? callback, bool includeActivityInstanceId = 
 432    {
 0433        return CreateBookmark(new()
 0434        {
 0435            Stimulus = stimulus,
 0436            Callback = callback,
 0437            IncludeActivityInstanceId = includeActivityInstanceId,
 0438            Metadata = customProperties
 0439        });
 440    }
 441
 442    /// <summary>
 443    /// Creates a bookmark for the current activity execution context.
 444    /// </summary>
 445    /// <param name="stimulus">The payload to associate with the bookmark.</param>
 446    /// <param name="includeActivityInstanceId">Specifies whether to include the activity instance ID in the bookmark in
 447    /// <param name="customProperties">Additional custom properties to associate with the bookmark. Defaults to null.</p
 448    /// <returns>The created bookmark.</returns>
 449    public Bookmark CreateBookmark(object stimulus, bool includeActivityInstanceId, IDictionary<string, string>? customP
 450    {
 0451        return CreateBookmark(new()
 0452        {
 0453            Stimulus = stimulus,
 0454            IncludeActivityInstanceId = includeActivityInstanceId,
 0455            Metadata = customProperties
 0456        });
 457    }
 458
 459    /// <summary>
 460    /// Creates a bookmark so that this activity can be resumed at a later time.
 461    /// </summary>
 462    /// <param name="stimulus">The payload to associate with the bookmark.</param>
 463    /// <param name="metadata">Custom properties to associate with the bookmark.</param>
 464    /// <returns>The created bookmark.</returns>
 465    public Bookmark CreateBookmark(object stimulus, IDictionary<string, string>? metadata = null)
 466    {
 9467        return CreateBookmark(new()
 9468        {
 9469            Stimulus = stimulus,
 9470            Metadata = metadata
 9471        });
 472    }
 473
 474    /// <summary>
 475    /// Creates a bookmark so that this activity can be resumed at a later time.
 476    /// Creating a bookmark will automatically suspend the workflow after all pending activities have executed.
 477    /// </summary>
 478    public Bookmark CreateBookmark(CreateBookmarkArgs? options = null)
 479    {
 73480        var payload = options?.Stimulus;
 73481        var callback = options?.Callback;
 73482        var bookmarkName = options?.BookmarkName ?? Activity.Type;
 73483        var bookmarkHasher = GetRequiredService<IStimulusHasher>();
 73484        var identityGenerator = GetRequiredService<IIdentityGenerator>();
 73485        var includeActivityInstanceId = options?.IncludeActivityInstanceId ?? true;
 73486        var hash = bookmarkHasher.Hash(bookmarkName, payload, includeActivityInstanceId ? Id : null);
 73487        var bookmarkId = options?.BookmarkId ?? identityGenerator.GenerateId();
 488
 73489        var bookmark = new Bookmark(
 73490            bookmarkId,
 73491            bookmarkName,
 73492            hash,
 73493            payload,
 73494            Activity.Id,
 73495            ActivityNode.NodeId,
 73496            Id,
 73497            _systemClock.UtcNow,
 73498            options?.AutoBurn ?? true,
 73499            callback?.Method.Name,
 73500            options?.AutoComplete ?? true,
 73501            options?.Metadata);
 502
 73503        AddBookmark(bookmark);
 73504        return bookmark;
 505    }
 506
 507    /// <summary>
 508    /// Clear all bookmarks.
 509    /// </summary>
 510    public void ClearBookmarks()
 511    {
 3404512        _newBookmarks.Clear();
 3479513        WorkflowExecutionContext.Bookmarks.RemoveWhere(x => x.ActivityInstanceId == Id);
 3404514        Taint();
 3404515    }
 516
 517    /// <summary>
 518    /// Returns a property value associated with the current activity context.
 519    /// </summary>
 1421520    public T? GetProperty<T>(string key) => Properties.TryGetValue<T?>(key, out var value) ? value : default;
 521
 522    /// <summary>
 523    /// Returns a property value associated with the current activity context.
 524    /// </summary>
 525    public T GetProperty<T>(string key, Func<T> defaultValue)
 526    {
 129527        if (Properties.TryGetValue<T?>(key, out var value))
 96528            return value!;
 529
 33530        value = defaultValue();
 33531        Properties[key] = value!;
 532
 33533        return value!;
 534    }
 535
 536    /// <summary>
 537    /// Stores a property associated with the current activity context.
 538    /// </summary>
 123539    public void SetProperty<T>(string key, T? value) => Properties[key] = value!;
 540
 541    /// <summary>
 542    /// Updates a property associated with the current activity context.
 543    /// </summary>
 544    public T UpdateProperty<T>(string key, Func<T?, T> updater) where T : notnull
 545    {
 382546        var value = GetProperty<T?>(key);
 382547        value = updater(value);
 382548        Properties[key] = value;
 382549        return value;
 550    }
 551
 552    /// <summary>
 553    /// Removes a property associated with the current activity context.
 554    /// </summary>
 555    /// <param name="key">The property key.</param>
 0556    public void RemoveProperty(string key) => Properties.Remove(key);
 557
 558    /// <summary>
 559    /// Returns a metadata value associated with the current activity context.
 560    /// </summary>
 0561    public T? GetMetadata<T>(string key) => Metadata.TryGetValue<T?>(key, out var value) ? value : default;
 562
 563    /// <summary>
 564    /// Returns a metadata value associated with the current activity context.
 565    /// </summary>
 566    public T GetMetadata<T>(string key, Func<T> defaultValue)
 567    {
 29568        if (Metadata.TryGetValue<T?>(key, out var value))
 13569            return value!;
 570
 16571        value = defaultValue();
 16572        Metadata[key] = value!;
 573
 16574        return value!;
 575    }
 576
 577    /// <summary>
 578    /// Stores a metadata value associated with the current activity context.
 579    /// </summary>
 4580    public void SetMetadata<T>(string key, T? value) => Metadata[key] = value!;
 581
 582    /// <summary>
 583    /// Updates a metadata value associated with the current activity context.
 584    /// </summary>
 585    public T UpdateMetadata<T>(string key, Func<T?, T> updater) where T : notnull
 586    {
 0587        var value = GetMetadata<T?>(key);
 0588        value = updater(value);
 0589        Metadata[key] = value;
 0590        return value;
 591    }
 592
 593    /// <summary>
 594    /// Removes a metadata value associated with the current activity context.
 595    /// </summary>
 596    /// <param name="key">The metadata key.</param>
 0597    public void RemoveMetadata(string key) => Metadata.Remove(key);
 598
 599    /// <summary>
 600    /// Resolves a required service using the service provider.
 601    /// </summary>
 602    /// <typeparam name="T">The service type.</typeparam>
 603    /// <returns>The resolved service.</returns>
 33563604    public T GetRequiredService<T>() where T : notnull => WorkflowExecutionContext.GetRequiredService<T>();
 605
 606    /// <summary>
 607    /// Resolves a required service using the service provider.
 608    /// </summary>
 609    /// <param name="serviceType">The service type.</param>
 610    /// <returns>The resolved service.</returns>
 3046611    public object GetRequiredService(Type serviceType) => WorkflowExecutionContext.GetRequiredService(serviceType);
 612
 613    /// <summary>
 614    /// Resolves a service using the service provider. If not found, a new instance is created.
 615    /// </summary>
 616    /// <typeparam name="T">The service type.</typeparam>
 617    /// <returns>The resolved service.</returns>
 0618    public T GetOrCreateService<T>() where T : notnull => WorkflowExecutionContext.GetOrCreateService<T>();
 619
 620    /// <summary>
 621    /// Resolves a service using the service provider. If not found, a new instance is created.
 622    /// </summary>
 623    /// <param name="serviceType">The service type.</param>
 624    /// <returns>The resolved service.</returns>
 0625    public object GetOrCreateService(Type serviceType) => WorkflowExecutionContext.GetOrCreateService(serviceType);
 626
 627    /// <summary>
 628    /// Resolves a service using the service provider.
 629    /// </summary>
 630    /// <typeparam name="T">The service type.</typeparam>
 631    /// <returns>The resolved service.</returns>
 586632    public T? GetService<T>() where T : notnull => WorkflowExecutionContext.GetService<T>();
 633
 634    /// <summary>
 635    /// Resolves all services of the specified type using the service provider.
 636    /// </summary>
 637    /// <typeparam name="T">The service type.</typeparam>
 638    /// <returns>The resolved services.</returns>
 266639    public IEnumerable<T> GetServices<T>() where T : notnull => WorkflowExecutionContext.GetServices<T>();
 640
 641    /// <summary>
 642    /// Resolves a service using the service provider.
 643    /// </summary>
 644    /// <param name="serviceType">The service type.</param>
 645    /// <returns>The resolved service.</returns>
 0646    public object? GetService(Type serviceType) => WorkflowExecutionContext.GetService(serviceType);
 647
 648    /// <summary>
 649    /// Gets the value of the specified input.
 650    /// </summary>
 651    /// <param name="input">The input.</param>
 652    /// <typeparam name="T">The type of the input.</typeparam>
 653    /// <returns>The input value.</returns>
 2856654    public T? Get<T>(Input<T>? input) => input == null ? default : Get<T>(input.MemoryBlockReference());
 655
 656    /// <summary>
 657    /// Gets the value of the specified output.
 658    /// </summary>
 659    /// <param name="output">The output.</param>
 660    /// <typeparam name="T">The type of the output.</typeparam>
 661    /// <returns>The output value.</returns>
 0662    public T? Get<T>(Output<T>? output) => output == null ? default : Get<T>(output.MemoryBlockReference());
 663
 664    /// <summary>
 665    /// Gets the value of the specified output.
 666    /// </summary>
 667    /// <param name="output">The output.</param>
 668    /// <returns>The output value.</returns>
 4669    public object? Get(Output? output) => output == null ? null : Get(output.MemoryBlockReference());
 670
 671    /// <summary>
 672    /// Gets the value of the specified memory block.
 673    /// </summary>
 674    /// <param name="blockReference">The memory block reference.</param>
 675    /// <returns>The memory block value.</returns>
 676    /// <exception cref="InvalidOperationException">The memory block does not exist.</exception>
 677    public object? Get(MemoryBlockReference blockReference)
 678    {
 2253679        return !TryGet(blockReference, out var value)
 2253680            ? throw new InvalidOperationException($"The memory block '{blockReference}' does not exist.")
 2253681            : value;
 682    }
 683
 684    /// <summary>
 685    /// Gets the value of the specified memory block.
 686    /// </summary>
 687    /// <param name="blockReference">The memory block reference.</param>
 688    /// <typeparam name="T">The type of the memory block.</typeparam>
 689    /// <returns>The memory block value.</returns>
 690    public T? Get<T>(MemoryBlockReference blockReference)
 691    {
 2123692        var value = Get(blockReference);
 2123693        return value != null ? value.ConvertTo<T>() : default;
 694    }
 695
 696    /// <summary>
 697    /// Tries to get the value of the specified memory block.
 698    /// </summary>
 699    /// <param name="blockReference">The memory block reference.</param>
 700    /// <param name="value">The memory block value.</param>
 701    /// <returns>True if the memory block exists, false otherwise.</returns>
 702    public bool TryGet(MemoryBlockReference blockReference, out object? value)
 703    {
 704        // First, try to get the value from the memory register
 2439705        var memoryBlock = GetMemoryBlock(blockReference);
 706
 2439707        if (memoryBlock != null)
 708        {
 2439709            value = memoryBlock.Value;
 2439710            return true;
 711        }
 712
 713        // Handle Literal references as a fallback - they can hold their value directly
 0714        if (blockReference is Literal literal)
 715        {
 0716            value = literal.Value;
 0717            return true;
 718        }
 719
 0720        value = null;
 0721        return false;
 722    }
 723
 724    /// <summary>
 725    /// Sets a value at the specified memory block.
 726    /// </summary>
 727    /// <param name="blockReference">The memory block reference.</param>
 728    /// <param name="value">The value to set.</param>
 729    /// <param name="configure">An optional callback that can be used to configure the memory block.</param>
 6730    public void Set(MemoryBlockReference blockReference, object? value, Action<MemoryBlock>? configure = null) => Expres
 731
 732    /// <summary>
 733    /// Sets a value at the specified output.
 734    /// </summary>
 735    /// <param name="output">The output.</param>
 736    /// <param name="value">The value to set.</param>
 737    /// <param name="outputName">The name of the output.</param>
 738    /// <typeparam name="T">The type of the output.</typeparam>
 1694739    public void Set<T>(Output<T>? output, T? value, [CallerArgumentExpression("output")] string? outputName = null) => S
 740
 741    /// <summary>
 742    /// Sets a value at the specified output.
 743    /// </summary>
 744    /// <param name="output">The output.</param>
 745    /// <param name="value">The value to set.</param>
 746    /// <param name="outputName">The name of the output.</param>
 747    public void Set(Output? output, object? value, [CallerArgumentExpression("output")] string? outputName = null)
 748    {
 749        // Store the value in the expression execution memory block.
 1722750        ExpressionExecutionContext.Set(output, value);
 751
 752        // Also store the value in the workflow execution transient activity output register.
 1722753        WorkflowExecutionContext.RecordActivityOutput(this, outputName, value);
 1722754    }
 755
 756    /// <summary>
 757    /// Removes all completion callbacks for the current activity.
 758    /// </summary>
 759    public void ClearCompletionCallbacks()
 760    {
 4921761        var entriesToRemove = WorkflowExecutionContext.CompletionCallbacks.Where(x => x.Owner == this).ToList();
 3404762        WorkflowExecutionContext.RemoveCompletionCallbacks(entriesToRemove);
 3404763    }
 764
 765    public void Taint()
 766    {
 17275767        if (!IsDirty)
 3854768            IsDirty = true;
 17275769    }
 770
 771    public void ClearTaint()
 772    {
 3413773        if (IsDirty)
 3413774            IsDirty = false;
 3413775    }
 776
 777    internal void IncrementExecutionCount()
 778    {
 3302779        _executionCount++;
 3302780    }
 781
 782    private MemoryBlock? GetMemoryBlock(MemoryBlockReference locationBlockReference)
 783    {
 2439784        return ExpressionExecutionContext.TryGetBlock(locationBlockReference, out var memoryBlock) ? memoryBlock : null;
 785    }
 786
 787    void IDisposable.Dispose()
 788    {
 0789    }
 790}

/home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Workflows.Core/Contexts/ActivityExecutionContext.ExecutionLogEntry.cs

#LineLine coverage
 1using Elsa.Extensions;
 2using Elsa.Workflows.Models;
 3
 4namespace Elsa.Workflows;
 5
 6public partial class ActivityExecutionContext
 7{
 8    /// <summary>
 9    /// Adds a new <see cref="WorkflowExecutionLogEntry"/> to the execution log of the current <see cref="Workflows.Work
 10    /// </summary>
 11    /// <param name="eventName">The name of the event.</param>
 12    /// <param name="message">The message of the event.</param>
 13    /// <param name="source">The source of the activity. For example, the source file name and line number in case of co
 14    /// <param name="payload">Any contextual data related to this event.</param>
 15    /// <returns>Returns the created <see cref="WorkflowExecutionLogEntry"/>.</returns>
 16    public WorkflowExecutionLogEntry AddExecutionLogEntry(string eventName, string? message = null, string? source = nul
 17    {
 679218        var logEntry = new WorkflowExecutionLogEntry(
 679219            Id,
 679220            ParentActivityExecutionContext?.Id,
 679221            Activity.Id,
 679222            Activity.Type,
 679223            Activity.Version,
 679224            Activity.Name,
 679225            NodeId,
 679226            null,
 679227            _systemClock.UtcNow,
 679228            WorkflowExecutionContext.ExecutionLogSequence++,
 679229            eventName,
 679230            message,
 679231            source ?? Activity.GetSource(),
 679232            payload);
 33
 679234        WorkflowExecutionContext.ExecutionLog.Add(logEntry);
 679235        return logEntry;
 36    }
 37}

Methods/Properties

CanCancelActivity()
CancelActivityAsync()
CancelChildActivitiesAsync()
CompleteActivityAsync()
CompleteActivityWithOutcomesAsync(System.String[])
CompleteCompositeAsync()
.ctor(System.String,Elsa.Workflows.WorkflowExecutionContext,Elsa.Workflows.ActivityExecutionContext,Elsa.Workflows.IActivity,Elsa.Workflows.Models.ActivityDescriptor,System.DateTimeOffset,System.Object,Elsa.Common.ISystemClock,System.Threading.CancellationToken)
get_Id()
get_StartedAt()
get_Tag()
get_CompletedAt()
get_IsCompleted()
get_IsExecuting()
get_AggregateFaultCount()
get_WorkflowExecutionContext()
get_ParentActivityExecutionContext()
set_ParentActivityExecutionContext(Elsa.Workflows.ActivityExecutionContext)
get_ExpressionExecutionContext()
get_Variables()
get_DynamicVariables()
get_Activity()
get_ActivityDescriptor()
get_CancellationToken()
get_Status()
set_Status(Elsa.Workflows.ActivityStatus)
EnterExecution()
TransitionTo(Elsa.Workflows.ActivityStatus)
get_Exception()
set_Exception(System.Exception)
get_Properties()
get_TransientProperties()
get_Metadata()
get_ActivityNode()
get_NodeId()
get_Children()
get_Bookmarks()
get_NewBookmarks()
get_ExecutionCount()
get_WorkflowInput()
get_ActivityInput()
get_JournalData()
get_ActivityState()
get_IsDirty()
ScheduleActivityAsync(Elsa.Workflows.IActivity,Elsa.Workflows.ActivityCompletionCallback,System.Object,System.Collections.Generic.IEnumerable`1<Elsa.Workflows.Memory.Variable>)
ScheduleActivityAsync()
ScheduleActivityAsync()
ScheduleActivityAsync()
ScheduleActivitiesAsync()
ScheduleActivities(System.Collections.Generic.IEnumerable`1<Elsa.Workflows.IActivity>,Elsa.Workflows.ActivityCompletionCallback,System.Object,System.Collections.Generic.IEnumerable`1<Elsa.Workflows.Memory.Variable>)
ScheduleActivities()
CreateBookmarks(System.Collections.Generic.IEnumerable`1<System.Object>,Elsa.Workflows.ExecuteActivityDelegate,System.Boolean,System.String)
AddBookmarks(System.Collections.Generic.IEnumerable`1<Elsa.Workflows.Models.Bookmark>)
AddBookmark(Elsa.Workflows.Models.Bookmark)
CreateBookmark(Elsa.Workflows.ExecuteActivityDelegate,System.Collections.Generic.IDictionary`2<System.String,System.String>)
CreateBookmark(System.Object,Elsa.Workflows.ExecuteActivityDelegate,System.Boolean,System.Collections.Generic.IDictionary`2<System.String,System.String>)
CreateBookmark(System.Object,System.Boolean,System.Collections.Generic.IDictionary`2<System.String,System.String>)
CreateBookmark(System.Object,System.Collections.Generic.IDictionary`2<System.String,System.String>)
CreateBookmark(Elsa.Workflows.Models.CreateBookmarkArgs)
ClearBookmarks()
GetProperty(System.String)
GetProperty(System.String,System.Func`1<T>)
SetProperty(System.String,T)
UpdateProperty(System.String,System.Func`2<T,T>)
RemoveProperty(System.String)
GetMetadata(System.String)
GetMetadata(System.String,System.Func`1<T>)
SetMetadata(System.String,T)
UpdateMetadata(System.String,System.Func`2<T,T>)
RemoveMetadata(System.String)
GetRequiredService()
GetRequiredService(System.Type)
GetOrCreateService()
GetOrCreateService(System.Type)
GetService()
GetServices()
GetService(System.Type)
Get(Elsa.Workflows.Models.Input`1<T>)
Get(Elsa.Workflows.Models.Output`1<T>)
Get(Elsa.Workflows.Models.Output)
Get(Elsa.Expressions.Models.MemoryBlockReference)
Get(Elsa.Expressions.Models.MemoryBlockReference)
TryGet(Elsa.Expressions.Models.MemoryBlockReference,System.Object&)
Set(Elsa.Expressions.Models.MemoryBlockReference,System.Object,System.Action`1<Elsa.Expressions.Models.MemoryBlock>)
Set(Elsa.Workflows.Models.Output`1<T>,T,System.String)
Set(Elsa.Workflows.Models.Output,System.Object,System.String)
ClearCompletionCallbacks()
Taint()
ClearTaint()
IncrementExecutionCount()
GetMemoryBlock(Elsa.Expressions.Models.MemoryBlockReference)
System.IDisposable.Dispose()
AddExecutionLogEntry(System.String,System.String,System.String,System.Object)