< Summary

Line coverage
84%
Covered lines: 256
Uncovered lines: 46
Coverable lines: 302
Total lines: 951
Line coverage: 84.7%
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%11100%
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    {
 340815        var outcomes = result as Outcomes;
 16
 17        // If the activity is executing in the background, simply capture the result and return.
 340818        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.
 340828        if (Status != ActivityStatus.Running)
 729            return;
 30
 31        // Cancel any non-completed child activities.
 608932        var childContexts = Children.Where(x => x.CanCancelActivity()).ToList();
 33
 681034        foreach (var childContext in childContexts)
 435            await childContext.CancelActivityAsync();
 36
 37        // Mark the activity as complete.
 340138        TransitionTo(ActivityStatus.Completed);
 39
 40        // Record the outcomes, if any.
 340141        if (outcomes != null)
 10442            JournalData["Outcomes"] = outcomes.Names;
 43
 44        // Add an execution log entry.
 340145        AddExecutionLogEntry("Completed");
 46
 47        // Send a signal.
 340148        await this.SendSignalAsync(new ActivityCompleted(result));
 49
 50        // Clear bookmarks.
 340151        ClearBookmarks();
 343452        WorkflowExecutionContext.Bookmarks.RemoveWhere(x => x.ActivityInstanceId == Id);
 53
 54        // Remove completion callbacks.
 340155        ClearCompletionCallbacks();
 56
 57        // Remove all associated variables, unless this is the root context - in which case we want to keep the variable
 340158        if (ParentActivityExecutionContext != null)
 59        {
 275160            var variablePersistenceManager = GetRequiredService<IVariablePersistenceManager>();
 275161            await variablePersistenceManager.DeleteVariablesAsync(this);
 62        }
 63
 64        // Update the completed at timestamp.
 340165        CompletedAt = WorkflowExecutionContext.SystemClock.UtcNow;
 340866    }
 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.
 387927    private List<Bookmark> _newBookmarks = [];
 28
 29    /// <summary>
 30    /// Initializes a new instance of the <see cref="ActivityExecutionContext"/> class.
 31    /// </summary>
 387932    public ActivityExecutionContext(
 387933        string id,
 387934        WorkflowExecutionContext workflowExecutionContext,
 387935        ActivityExecutionContext? parentActivityExecutionContext,
 387936        IActivity activity,
 387937        ActivityDescriptor activityDescriptor,
 387938        DateTimeOffset startedAt,
 387939        object? tag,
 387940        ISystemClock systemClock,
 387941        CancellationToken cancellationToken)
 42    {
 387943        _systemClock = systemClock;
 387944        Properties = new ChangeTrackingDictionary<string, object>(Taint);
 387945        Metadata = new ChangeTrackingDictionary<string, object>(Taint);
 387946        ActivityState = new ChangeTrackingDictionary<string, object>(Taint);
 387947        ActivityInput = new ChangeTrackingDictionary<string, object>(Taint);
 387948        WorkflowExecutionContext = workflowExecutionContext;
 387949        ParentActivityExecutionContext = parentActivityExecutionContext;
 387950        var expressionExecutionContextProps = ExpressionExecutionContextExtensions.CreateActivityExecutionContextPropert
 387951        expressionExecutionContextProps[ExpressionExecutionContextExtensions.ActivityKey] = activity;
 387952        ExpressionExecutionContext = new(workflowExecutionContext.ServiceProvider, new(), parentActivityExecutionContext
 387953        Activity = activity;
 387954        ActivityDescriptor = activityDescriptor;
 387955        StartedAt = startedAt;
 387956        Status = ActivityStatus.Pending;
 387957        Tag = tag;
 387958        CancellationToken = cancellationToken;
 387959        Id = id;
 387960        _publisher = GetRequiredService<INotificationSender>();
 387961    }
 62
 63    /// <summary>
 64    /// The ID of the current activity execution context.
 65    /// </summary>
 3178766    public string Id { get; set; }
 67
 68    /// <summary>
 69    /// The time at which the activity execution context was created.
 70    /// </summary>
 814171    public DateTimeOffset StartedAt { get; set; }
 72
 73    /// <summary>
 74    /// An optional tag to associate with the activity execution.
 75    /// </summary>
 746676    public object? Tag { get; set; }
 77
 78    /// <summary>
 79    /// The time at which the activity execution context was completed.
 80    /// </summary>
 766381    public DateTimeOffset? CompletedAt { get; set; }
 82
 83    /// <summary>
 84    /// Returns true if the activity execution context has completed.
 85    /// </summary>
 1347286    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>
 168781107    public WorkflowExecutionContext WorkflowExecutionContext { get; }
 108
 109    /// <summary>
 110    /// The parent activity execution context, if any.
 111    /// </summary>
 112    public ActivityExecutionContext? ParentActivityExecutionContext
 113    {
 62135114        get => _parentActivityExecutionContext;
 115        internal set
 116        {
 3984117            _parentActivityExecutionContext = value;
 3984118            _parentActivityExecutionContext?.Children.Add(this);
 2912119        }
 120    }
 121
 122    /// <summary>
 123    /// The expression execution context.
 124    /// </summary>
 45654125    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>
 11267154    public ICollection<Variable> DynamicVariables { get; set; } = new List<Variable>();
 155
 156    /// <summary>
 157    /// The currently executing activity.
 158    /// </summary>
 200791159    public IActivity Activity { get; set; }
 160
 161    /// <summary>
 162    /// The activity descriptor.
 163    /// </summary>
 26035164    public ActivityDescriptor ActivityDescriptor { get; }
 165
 166    /// <summary>
 167    /// A cancellation token to use when invoking asynchronous operations.
 168    /// </summary>
 34430169    public CancellationToken CancellationToken { get; }
 170
 171    /// <summary>
 172    /// The current status of the activity.
 173    /// </summary>
 174    public ActivityStatus Status
 175    {
 40259176        get => _status;
 177        private set
 178        {
 11150179            if (value == _status)
 3918180                return;
 181
 7232182            _status = value;
 7232183            Taint();
 7232184        }
 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    {
 7271197        Status = status;
 7271198    }
 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 />
 12892214    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>
 44570220    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>
 8201225    public IDictionary<string, object> Metadata { get; private set; }
 226
 227    /// <summary>
 228    /// Returns the <see cref="ActivityNode"/> metadata about the current activity.
 229    /// </summary>
 31921230    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
 11155236    public string NodeId => ActivityNode.NodeId;
 237
 14655238    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>
 7887263    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
 7466269    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>
 10557274    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>
 31379279    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    {
 76403        _newBookmarks.Add(bookmark);
 76404        WorkflowExecutionContext.Bookmarks.Add(bookmark);
 76405        Taint();
 76406    }
 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    {
 3416        return CreateBookmark(new()
 3417        {
 3418            Callback = callback,
 3419            Metadata = metadata
 3420        });
 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    {
 76480        var payload = options?.Stimulus;
 76481        var callback = options?.Callback;
 76482        var bookmarkName = options?.BookmarkName ?? Activity.Type;
 76483        var bookmarkHasher = GetRequiredService<IStimulusHasher>();
 76484        var identityGenerator = GetRequiredService<IIdentityGenerator>();
 76485        var includeActivityInstanceId = options?.IncludeActivityInstanceId ?? true;
 76486        var hash = bookmarkHasher.Hash(bookmarkName, payload, includeActivityInstanceId ? Id : null);
 76487        var bookmarkId = options?.BookmarkId ?? identityGenerator.GenerateId();
 488
 76489        var bookmark = new Bookmark(
 76490            bookmarkId,
 76491            bookmarkName,
 76492            hash,
 76493            payload,
 76494            Activity.Id,
 76495            ActivityNode.NodeId,
 76496            Id,
 76497            _systemClock.UtcNow,
 76498            options?.AutoBurn ?? true,
 76499            callback?.Method.Name,
 76500            options?.AutoComplete ?? true,
 76501            options?.Metadata);
 502
 76503        AddBookmark(bookmark);
 76504        return bookmark;
 505    }
 506
 507    /// <summary>
 508    /// Clear all bookmarks.
 509    /// </summary>
 510    public void ClearBookmarks()
 511    {
 3405512        _newBookmarks.Clear();
 3480513        WorkflowExecutionContext.Bookmarks.RemoveWhere(x => x.ActivityInstanceId == Id);
 3405514        Taint();
 3405515    }
 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>
 33600604    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>
 3048611    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>
 2861654    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    {
 2254679        return !TryGet(blockReference, out var value)
 2254680            ? throw new InvalidOperationException($"The memory block '{blockReference}' does not exist.")
 2254681            : 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    {
 2124692        var value = Get(blockReference);
 2124693        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
 2440705        var memoryBlock = GetMemoryBlock(blockReference);
 706
 2440707        if (memoryBlock != null)
 708        {
 2440709            value = memoryBlock.Value;
 2440710            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    {
 4922761        var entriesToRemove = WorkflowExecutionContext.CompletionCallbacks.Where(x => x.Owner == this).ToList();
 3405762        WorkflowExecutionContext.RemoveCompletionCallbacks(entriesToRemove);
 3405763    }
 764
 765    public void Taint()
 766    {
 17284767        if (!IsDirty)
 3856768            IsDirty = true;
 17284769    }
 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    {
 2440784        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    {
 679318        var logEntry = new WorkflowExecutionLogEntry(
 679319            Id,
 679320            ParentActivityExecutionContext?.Id,
 679321            Activity.Id,
 679322            Activity.Type,
 679323            Activity.Version,
 679324            Activity.Name,
 679325            NodeId,
 679326            null,
 679327            _systemClock.UtcNow,
 679328            WorkflowExecutionContext.ExecutionLogSequence++,
 679329            eventName,
 679330            message,
 679331            source ?? Activity.GetSource(),
 679332            payload);
 33
 679334        WorkflowExecutionContext.ExecutionLog.Add(logEntry);
 679335        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)