< Summary

Information
Class: Elsa.Workflows.Activity
Assembly: Elsa.Workflows.Core
File(s): /home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Workflows.Core/Abstractions/Activity.cs
Line coverage
87%
Covered lines: 50
Uncovered lines: 7
Coverable lines: 57
Total lines: 209
Line coverage: 87.7%
Branch coverage
100%
Covered branches: 6
Total branches: 6
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

/home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Workflows.Core/Abstractions/Activity.cs

#LineLine coverage
 1using System.Diagnostics;
 2using System.Text.Json.Serialization;
 3using Elsa.Extensions;
 4using Elsa.Workflows.Behaviors;
 5using Elsa.Workflows.Helpers;
 6using Elsa.Workflows.Models;
 7using Elsa.Workflows.Serialization.Converters;
 8using JetBrains.Annotations;
 9
 10namespace Elsa.Workflows;
 11
 12/// <summary>
 13/// Base class for custom activities.
 14/// </summary>
 15[DebuggerDisplay("{Type} - {Id}")]
 16[UsedImplicitly(ImplicitUseTargetFlags.WithInheritors | ImplicitUseTargetFlags.Members)]
 17public abstract class Activity : IActivity, ISignalHandler
 18{
 2210919    private readonly ICollection<SignalHandlerRegistration> _signalReceivedHandlers = new List<SignalHandlerRegistration
 20
 21    /// <summary>
 22    /// Constructor.
 23    /// </summary>
 2210924    protected Activity(string? source = null, int? line = null)
 25    {
 2210926        this.SetSource(source, line);
 2210927        Type = ActivityTypeNameHelper.GenerateTypeName(GetType());
 2210928        Version = 1;
 2210929        Behaviors.Add<ScheduledChildCallbackBehavior>(this);
 2210930    }
 31
 32    /// <inheritdoc />
 033    protected Activity(string activityType, int version = 1, string? source = null, int? line = null) : this(source, lin
 34    {
 035        Type = activityType;
 036        Version = version;
 037    }
 38
 39    /// <inheritdoc />
 28061440    public string Id { get; set; } = null!;
 41
 42    /// <inheritdoc />
 4209243    public string NodeId { get; set; } = null!;
 44
 45    /// <inheritdoc />
 1986146    public string? Name { get; set; }
 47
 48    /// <inheritdoc />
 11342549    public string Type { get; set; }
 50
 51    /// <inheritdoc />
 9068352    public int Version { get; set; }
 53
 54    /// <summary>
 55    /// A flag indicating whether this activity can be used for starting a workflow.
 56    /// Usually used for triggers, but also used to disambiguate between two or more starting activities and no starting
 57    /// </summary>
 58    [JsonIgnore]
 59    public bool CanStartWorkflow
 60    {
 661        get => this.GetCanStartWorkflow();
 45962        set => this.SetCanStartWorkflow(value);
 63    }
 64
 65    /// <summary>
 66    /// A flag indicating if this activity should execute synchronously or asynchronously.
 67    /// By default, activities with an <see cref="ActivityKind"/> of <see cref="Action"/>, <see cref="Task"/> or <see cr
 68    /// will execute synchronously, while activities of the <see cref="ActivityKind.Job"/> kind will execute asynchronou
 69    /// </summary>
 70    [JsonIgnore]
 71    public bool? RunAsynchronously
 72    {
 673        get => this.GetRunAsynchronously();
 140074        set => this.SetRunAsynchronously(value);
 75    }
 76
 77    [JsonIgnore]
 78    public string? CommitStrategy
 79    {
 680        get => this.GetCommitStrategy();
 081        set => this.SetCommitStrategy(value);
 82    }
 83
 84    /// <inheritdoc />
 85    [JsonConverter(typeof(PolymorphicObjectConverterFactory))]
 9910086    public IDictionary<string, object> CustomProperties { get; set; } = new Dictionary<string, object>();
 87
 88    /// <inheritdoc />
 89    [JsonIgnore]
 2232590    public IDictionary<string, object> SyntheticProperties { get; set; } = new Dictionary<string, object>();
 91
 92    /// <inheritdoc />
 93    [JsonConverter(typeof(PolymorphicObjectConverterFactory))]
 3106494    public IDictionary<string, object> Metadata { get; set; } = new Dictionary<string, object>();
 95
 96    /// <summary>
 97    /// A collection of reusable behaviors to add to this activity.
 98    /// </summary>
 99    [JsonIgnore]
 65317100    public ICollection<IBehavior> Behaviors { get; } = new List<IBehavior>();
 101
 102    /// <summary>
 103    /// Override this method to return a value indicating whether the activity can execute.
 104    /// </summary>
 105    protected virtual ValueTask<bool> CanExecuteAsync(ActivityExecutionContext context)
 106    {
 3316107        var result = CanExecute(context);
 3316108        return new(result);
 109    }
 110
 111    /// <summary>
 112    /// Override this method to return a value indicating whether the activity can execute.
 113    /// </summary>
 114    protected virtual bool CanExecute(ActivityExecutionContext context)
 115    {
 3316116        return true;
 117    }
 118
 119    /// <summary>
 120    /// Override this method to implement activity-specific logic.
 121    /// </summary>
 122    protected virtual ValueTask ExecuteAsync(ActivityExecutionContext context)
 123    {
 742124        Execute(context);
 715125        return ValueTask.CompletedTask;
 126    }
 127
 128    /// <summary>
 129    /// Override this method to implement activity-specific logic.
 130    /// </summary>
 131    protected virtual void Execute(ActivityExecutionContext context)
 132    {
 25133    }
 134
 135    /// <summary>
 136    /// Override this method to handle any signals sent from downstream activities.
 137    /// </summary>
 138    protected virtual ValueTask OnSignalReceivedAsync(object signal, SignalContext context)
 139    {
 12840140        OnSignalReceived(signal, context);
 12840141        return ValueTask.CompletedTask;
 142    }
 143
 144    /// <summary>
 145    /// Override this method to handle any signals sent from downstream activities.
 146    /// </summary>
 147    protected virtual void OnSignalReceived(object signal, SignalContext context)
 148    {
 12840149    }
 150
 151    /// <summary>
 152    /// Register a signal handler delegate.
 153    /// </summary>
 16903154    protected void OnSignalReceived(Type signalType, Func<object, SignalContext, ValueTask> handler) => _signalReceivedH
 155
 156    /// <summary>
 157    /// Register a signal handler delegate.
 158    /// </summary>
 16905159    protected void OnSignalReceived<T>(Func<T, SignalContext, ValueTask> handler) => OnSignalReceived(typeof(T), (signal
 160
 161    /// <summary>
 162    /// Register a signal handler delegate.
 163    /// </summary>
 164    protected void OnSignalReceived<T>(Action<T, SignalContext> handler)
 165    {
 7175166        OnSignalReceived<T>((signal, context) =>
 7175167        {
 0168            handler(signal, context);
 0169            return ValueTask.CompletedTask;
 7175170        });
 7175171    }
 172
 173    /// <summary>
 174    /// Notify the workflow that this activity completed.
 175    /// </summary>
 176    protected async ValueTask CompleteAsync(ActivityExecutionContext context)
 177    {
 3178        await context.CompleteActivityAsync();
 3179    }
 180
 181    async ValueTask<bool> IActivity.CanExecuteAsync(ActivityExecutionContext context)
 182    {
 3316183        return await CanExecuteAsync(context);
 3316184    }
 185
 186    async ValueTask IActivity.ExecuteAsync(ActivityExecutionContext context)
 187    {
 3661188        await ExecuteAsync(context);
 189
 190        // Invoke behaviors.
 20430191        foreach (var behavior in Behaviors) await behavior.ExecuteAsync(context);
 3627192    }
 193
 194    async ValueTask ISignalHandler.ReceiveSignalAsync(object signal, SignalContext context)
 195    {
 196        // Give derived activity a chance to do something with the signal.
 12840197        await OnSignalReceivedAsync(signal, context);
 198
 199        // Invoke registered signal delegates for this particular type of signal.
 12840200        var signalType = signal.GetType();
 31426201        var handlers = _signalReceivedHandlers.Where(x => x.SignalType == signalType);
 202
 25684203        foreach (var registration in handlers)
 2204            await registration.Handler(signal, context);
 205
 206        // Invoke behaviors.
 66588207        foreach (var behavior in Behaviors) await behavior.ReceiveSignalAsync(signal, context);
 12840208    }
 209}