< Summary

Information
Class: Elsa.Workflows.Runtime.Features.WorkflowRuntimeFeature
Assembly: Elsa.Workflows.Runtime
File(s): /home/runner/work/elsa-core/elsa-core/src/modules/Elsa.Workflows.Runtime/Features/WorkflowRuntimeFeature.cs
Line coverage
94%
Covered lines: 179
Uncovered lines: 10
Coverable lines: 189
Total lines: 368
Line coverage: 94.7%
Branch coverage
70%
Covered branches: 7
Total branches: 10
Branch coverage: 70%
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.Runtime/Features/WorkflowRuntimeFeature.cs

#LineLine coverage
 1using System.Diagnostics.CodeAnalysis;
 2using System.Reflection;
 3using Elsa.Common.DistributedHosting;
 4using Elsa.Common.Features;
 5using Elsa.Common.RecurringTasks;
 6using Elsa.Extensions;
 7using Elsa.Features.Abstractions;
 8using Elsa.Features.Attributes;
 9using Elsa.Features.Services;
 10using Elsa.Mediator.Contracts;
 11using Elsa.Workflows.Features;
 12using Elsa.Workflows.Management;
 13using Elsa.Workflows.Management.Contracts;
 14using Elsa.Workflows.Management.Services;
 15using Elsa.Workflows.Runtime.ActivationValidators;
 16using Elsa.Workflows.Runtime.Entities;
 17using Elsa.Workflows.Runtime.Handlers;
 18using Elsa.Workflows.Runtime.Options;
 19using Elsa.Workflows.Runtime.Providers;
 20using Elsa.Workflows.Runtime.Stores;
 21using Elsa.Workflows.Runtime.Tasks;
 22using Elsa.Workflows.Runtime.UIHints;
 23using Medallion.Threading;
 24using Medallion.Threading.FileSystem;
 25using Microsoft.Extensions.DependencyInjection;
 26
 27namespace Elsa.Workflows.Runtime.Features;
 28
 29/// <summary>
 30/// Installs and configures workflow runtime features.
 31/// </summary>
 32[DependsOn(typeof(SystemClockFeature))]
 20033public class WorkflowRuntimeFeature(IModule module) : FeatureBase(module)
 34{
 36235    private IDictionary<string, DispatcherChannel> WorkflowDispatcherChannels { get; set; } = new Dictionary<string, Dis
 36
 37    /// <summary>
 38    /// A list of workflow builders configured during application startup.
 39    /// </summary>
 56840    public IDictionary<string, Func<IServiceProvider, ValueTask<IWorkflow>>> Workflows { get; set; } = new Dictionary<st
 41
 42    /// <summary>
 43    /// A factory that instantiates a concrete <see cref="IWorkflowRuntime"/>.
 44    /// </summary>
 56545    public Func<IServiceProvider, IWorkflowRuntime> WorkflowRuntime { get; set; } = sp => ActivatorUtilities.CreateInsta
 46
 47    /// <summary>
 48    /// A factory that instantiates an <see cref="IWorkflowDispatcher"/>.
 49    /// </summary>
 40050    public Func<IServiceProvider, IWorkflowDispatcher> WorkflowDispatcher { get; set; } = sp =>
 20051    {
 48152        var decoratedService = ActivatorUtilities.CreateInstance<BackgroundWorkflowDispatcher>(sp);
 48153        return ActivatorUtilities.CreateInstance<ValidatingWorkflowDispatcher>(sp, decoratedService);
 20054    };
 55
 56    /// <summary>
 57    /// A factory that instantiates an <see cref="IStimulusDispatcher"/>.
 58    /// </summary>
 41159    public Func<IServiceProvider, IStimulusDispatcher> StimulusDispatcher { get; set; } = sp => ActivatorUtilities.Creat
 60
 61    /// <summary>
 62    /// A factory that instantiates an <see cref="IWorkflowCancellationDispatcher"/>.
 63    /// </summary>
 40364    public Func<IServiceProvider, IWorkflowCancellationDispatcher> WorkflowCancellationDispatcher { get; set; } = sp => 
 65
 66    /// <summary>
 67    /// A factory that instantiates an <see cref="IBookmarkStore"/>.
 68    /// </summary>
 75769    public Func<IServiceProvider, IBookmarkStore> BookmarkStore { get; set; } = sp => sp.GetRequiredService<MemoryBookma
 70
 71    /// <summary>
 72    /// A factory that instantiates an <see cref="IBookmarkQueueStore"/>.
 73    /// </summary>
 75774    public Func<IServiceProvider, IBookmarkQueueStore> BookmarkQueueStore { get; set; } = sp => sp.GetRequiredService<Me
 75
 76    /// <summary>
 77    /// A factory that instantiates an <see cref="ITriggerStore"/>.
 78    /// </summary>
 64779    public Func<IServiceProvider, ITriggerStore> TriggerStore { get; set; } = sp => sp.GetRequiredService<MemoryTriggerS
 80
 81    /// <summary>
 82    /// A factory that instantiates an <see cref="IWorkflowExecutionLogStore"/>.
 83    /// </summary>
 64784    public Func<IServiceProvider, IWorkflowExecutionLogStore> WorkflowExecutionLogStore { get; set; } = sp => sp.GetRequ
 85
 86    /// <summary>
 87    /// A factory that instantiates an <see cref="IActivityExecutionStore"/>.
 88    /// </summary>
 63489    public Func<IServiceProvider, IActivityExecutionStore> ActivityExecutionLogStore { get; set; } = sp => sp.GetRequire
 90
 91    /// <summary>
 92    /// A factory that instantiates an <see cref="IDistributedLockProvider"/>.
 93    /// </summary>
 57194    public Func<IServiceProvider, IDistributedLockProvider> DistributedLockProvider { get; set; } = _ => new FileDistrib
 95
 96    /// <summary>
 97    /// A factory that instantiates an <see cref="ITaskDispatcher"/>.
 98    /// </summary>
 40099    public Func<IServiceProvider, ITaskDispatcher> RunTaskDispatcher { get; set; } = sp => sp.GetRequiredService<Backgro
 100
 101    /// <summary>
 102    /// A factory that instantiates an <see cref="IBackgroundActivityScheduler"/>.
 103    /// </summary>
 571104    public Func<IServiceProvider, IBackgroundActivityScheduler> BackgroundActivityScheduler { get; set; } = sp => Activa
 105
 106    /// <summary>
 107    /// A factory that instantiates a log record sink for an <see cref="ActivityExecutionRecord"/>.
 108    /// </summary>
 918109    public Func<IServiceProvider, ILogRecordSink<ActivityExecutionRecord>> ActivityExecutionLogSink { get; set; } = sp =
 110
 111    /// <summary>
 112    /// A factory that instantiates a log record sink for an <see cref="WorkflowExecutionLogRecord"/>.
 113    /// </summary>
 918114    public Func<IServiceProvider, ILogRecordSink<WorkflowExecutionLogRecord>> WorkflowExecutionLogSink { get; set; } = s
 115
 116    /// <summary>
 117    /// A factory that instantiates an <see cref="ICommandHandler"/>.
 118    /// </summary>
 200119    public Func<IServiceProvider, ICommandHandler> DispatchWorkflowCommandHandler { get; set; } = sp => sp.GetRequiredSe
 120
 121    /// <summary>
 122    /// A factory that instantiates an <see cref="IWorkflowResumer"/>.
 123    /// </summary>
 832124    public Func<IServiceProvider, IWorkflowResumer> WorkflowResumer { get; set; } = sp => sp.GetRequiredService<Workflow
 125
 126    /// <summary>
 127    /// A factory that instantiates an <see cref="IBookmarkQueueWorker"/>.
 128    /// </summary>
 673129    public Func<IServiceProvider, IBookmarkQueueWorker> BookmarkQueueWorker { get; set; } = sp => sp.GetRequiredService<
 130
 131    /// <summary>
 132    /// A delegate to configure the <see cref="DistributedLockingOptions"/>.
 133    /// </summary>
 571134    public Action<DistributedLockingOptions> DistributedLockingOptions { get; set; } = _ => { };
 135
 136    /// <summary>
 137    /// A delegate to configure the <see cref="WorkflowInboxCleanupOptions"/>.
 138    /// </summary>
 139    [Obsolete("Will be removed in a future version")]
 400140    public Action<WorkflowInboxCleanupOptions> WorkflowInboxCleanupOptions { get; set; } = _ => { };
 141
 142    /// <summary>
 143    /// A delegate to configure the <see cref="WorkflowDispatcherOptions"/>.
 144    /// </summary>
 562145    public Action<WorkflowDispatcherOptions> WorkflowDispatcherOptions { get; set; } = _ => { };
 146
 147    /// <summary>
 148    /// A delegate to configure the <see cref="BookmarkQueuePurgeOptions"/>.
 149    /// </summary>
 412150    public Action<BookmarkQueuePurgeOptions> BookmarkQueuePurgeOptions { get; set; } = _ => { };
 151
 152    /// <summary>
 153    /// Enables the workflow inbox cleanup job.
 154    /// </summary>
 155    public WorkflowRuntimeFeature EnableWorkflowInboxCleanupJob()
 156    {
 0157        Services.Configure<WorkflowInboxCleanupOptions>(options => { options.IsEnabled = true; });
 0158        return this;
 159    }
 160
 161    /// <summary>
 162    /// Disables the workflow inbox cleanup job.
 163    /// </summary>
 164    public WorkflowRuntimeFeature DisableWorkflowInboxCleanupJob()
 165    {
 0166        Services.Configure<WorkflowInboxCleanupOptions>(options => { options.IsEnabled = false; });
 0167        return this;
 168    }
 169
 170    /// <summary>
 171    /// Register the specified workflow type.
 172    /// </summary>
 173    public WorkflowRuntimeFeature AddWorkflow<T>() where T : IWorkflow
 174    {
 20175        Workflows.Add<T>();
 20176        return this;
 177    }
 178
 179    /// <summary>
 180    /// Register all workflows in the specified assembly.
 181    /// </summary>
 182    [RequiresUnreferencedCode("The assembly is required to be referenced.")]
 183    public WorkflowRuntimeFeature AddWorkflowsFrom(Assembly assembly)
 184    {
 6185        var workflowTypes = assembly.GetExportedTypes()
 414186            .Where(x => typeof(IWorkflow).IsAssignableFrom(x) && x is { IsAbstract: false, IsInterface: false, IsGeneric
 6187            .ToList();
 188
 390189        foreach (var workflowType in workflowTypes)
 189190            Workflows.Add(workflowType);
 191
 6192        return this;
 193    }
 194
 195    /// <summary>
 196    /// Adds a dispatcher channel.
 197    /// </summary>
 198    public WorkflowRuntimeFeature AddDispatcherChannel(string channel)
 199    {
 0200        return AddDispatcherChannel(new DispatcherChannel
 0201        {
 0202            Name = channel
 0203        });
 204    }
 205
 206    /// <summary>
 207    /// Adds a dispatcher channel.
 208    /// </summary>
 209    public WorkflowRuntimeFeature AddDispatcherChannel(DispatcherChannel channel)
 210    {
 0211        WorkflowDispatcherChannels[channel.Name] = channel;
 0212        return this;
 213    }
 214
 215    /// <inheritdoc />
 216    public override void Configure()
 217    {
 200218        Module.AddActivitiesFrom<WorkflowRuntimeFeature>();
 200219        Module.Configure<WorkflowsFeature>(workflows =>
 200220        {
 718221            workflows.CommitStateHandler = sp => sp.GetRequiredService<DefaultCommitStateHandler>();
 400222        });
 223
 200224        Services.Configure<RecurringTaskOptions>(options =>
 200225        {
 70226            options.Schedule.ConfigureTask<TriggerBookmarkQueueRecurringTask>(TimeSpan.FromSeconds(10));
 270227        });
 200228    }
 229
 230    /// <inheritdoc />
 231    public override void Apply()
 232    {
 233        // Options.
 200234        Services.Configure(DistributedLockingOptions);
 200235        Services.Configure(WorkflowInboxCleanupOptions);
 200236        Services.Configure(WorkflowDispatcherOptions);
 200237        Services.Configure(BookmarkQueuePurgeOptions);
 518238        Services.Configure<RuntimeOptions>(options => { options.Workflows = Workflows; });
 200239        Services.Configure<WorkflowDispatcherOptions>(options =>
 200240        {
 162241            options.Channels.AddRange(WorkflowDispatcherChannels.Values);
 362242        });
 243
 200244        Services
 200245            // Core.
 200246            .AddScoped<ITriggerIndexer, TriggerIndexer>()
 200247            .AddScoped<IWorkflowInstanceFactory, WorkflowInstanceFactory>()
 200248            .AddScoped<IWorkflowHostFactory, WorkflowHostFactory>()
 200249            .AddScoped<IBackgroundActivityInvoker, BackgroundActivityInvoker>()
 200250            .AddScoped(WorkflowRuntime)
 200251            .AddScoped(WorkflowDispatcher)
 200252            .AddScoped(StimulusDispatcher)
 200253            .AddScoped(WorkflowCancellationDispatcher)
 200254            .AddScoped(RunTaskDispatcher)
 200255            .AddScoped(ActivityExecutionLogSink)
 200256            .AddScoped(WorkflowExecutionLogSink)
 200257            .AddSingleton(BackgroundActivityScheduler)
 200258            .AddSingleton<RandomLongIdentityGenerator>()
 200259            .AddSingleton<IBookmarkQueueSignaler, BookmarkQueueSignaler>()
 200260            .AddScoped(BookmarkQueueWorker)
 200261            .AddScoped<IBookmarkManager, DefaultBookmarkManager>()
 200262            .AddScoped<IActivityExecutionManager, DefaultActivityExecutionManager>()
 200263            .AddScoped<IActivityExecutionStatsService, ActivityExecutionStatsService>()
 200264            .AddScoped<IActivityExecutionMapper, DefaultActivityExecutionMapper>()
 200265            .AddScoped<IWorkflowDefinitionStorePopulator, DefaultWorkflowDefinitionStorePopulator>()
 200266            .AddScoped<IRegistriesPopulator, DefaultRegistriesPopulator>()
 200267            .AddScoped<IWorkflowDefinitionsRefresher, WorkflowDefinitionsRefresher>()
 200268            .AddScoped<IWorkflowDefinitionsReloader, WorkflowDefinitionsReloader>()
 200269            .AddScoped<IWorkflowRegistry, DefaultWorkflowRegistry>()
 200270            .AddScoped<IWorkflowMatcher, WorkflowMatcher>()
 200271            .AddScoped<IWorkflowInvoker, WorkflowInvoker>()
 200272            .AddScoped<IStimulusSender, StimulusSender>()
 200273            .AddScoped<ITriggerBoundWorkflowService, TriggerBoundWorkflowService>()
 200274            .AddScoped<IBookmarkBoundWorkflowService, BookmarkBoundWorkflowService>()
 200275            .AddScoped<ITaskReporter, TaskReporter>()
 200276            .AddScoped<SynchronousTaskDispatcher>()
 200277            .AddScoped<BackgroundTaskDispatcher>()
 200278            .AddScoped<StoreActivityExecutionLogSink>()
 200279            .AddScoped<StoreWorkflowExecutionLogSink>()
 200280            .AddScoped<DispatchWorkflowCommandHandler>()
 200281            .AddScoped<IEventPublisher, EventPublisher>()
 200282            .AddScoped<IBookmarkUpdater, BookmarkUpdater>()
 200283            .AddScoped<IBookmarksPersister, BookmarksPersister>()
 200284            .AddScoped<IBookmarkResumer, BookmarkResumer>()
 200285            .AddScoped<IBookmarkQueue, StoreBookmarkQueue>()
 200286            .AddScoped(WorkflowResumer)
 200287            .AddScoped<WorkflowResumer>()
 200288            .AddScoped(BookmarkQueueWorker)
 200289            .AddScoped<BookmarkQueueWorker>()
 200290            .AddScoped<ITriggerInvoker, TriggerInvoker>()
 200291            .AddScoped<IWorkflowCanceler, WorkflowCanceler>()
 200292            .AddScoped<IWorkflowCancellationService, WorkflowCancellationService>()
 200293            .AddScoped<IWorkflowActivationStrategyEvaluator, DefaultWorkflowActivationStrategyEvaluator>()
 200294            .AddScoped<IWorkflowStarter, DefaultWorkflowStarter>()
 200295            .AddScoped<IWorkflowRestarter, DefaultWorkflowRestarter>()
 200296            .AddScoped<IBookmarkQueuePurger, DefaultBookmarkQueuePurger>()
 200297            .AddScoped<ILogRecordExtractor<WorkflowExecutionLogRecord>, WorkflowExecutionLogRecordExtractor>()
 200298            .AddScoped<IActivityPropertyLogPersistenceEvaluator, ActivityPropertyLogPersistenceEvaluator>()
 200299            .AddScoped<IBookmarkQueueProcessor, BookmarkQueueProcessor>()
 200300            .AddScoped<DefaultCommitStateHandler>()
 200301            .AddScoped<WorkflowHeartbeatGeneratorFactory>()
 200302
 200303            // Deprecated services.
 200304            .AddScoped<IWorkflowInbox, StimulusProxyWorkflowInbox>()
 200305
 200306            // Stores.
 200307            .AddScoped(BookmarkStore)
 200308            .AddScoped(BookmarkQueueStore)
 200309            .AddScoped(TriggerStore)
 200310            .AddScoped(WorkflowExecutionLogStore)
 200311            .AddScoped(ActivityExecutionLogStore)
 200312
 200313            // Lazy services.
 170314            .AddScoped<Func<IEnumerable<IWorkflowsProvider>>>(sp => sp.GetServices<IWorkflowsProvider>)
 672315            .AddScoped<Func<IEnumerable<IWorkflowMaterializer>>>(sp => sp.GetServices<IWorkflowMaterializer>)
 200316
 200317            // Noop stores.
 200318            .AddScoped<MemoryWorkflowExecutionLogStore>()
 200319            .AddScoped<MemoryActivityExecutionStore>()
 200320
 200321            // Memory stores.
 200322            .AddMemoryStore<StoredBookmark, MemoryBookmarkStore>()
 200323            .AddMemoryStore<StoredTrigger, MemoryTriggerStore>()
 200324            .AddMemoryStore<BookmarkQueueItem, MemoryBookmarkQueueStore>()
 200325            .AddMemoryStore<WorkflowExecutionLogRecord, MemoryWorkflowExecutionLogStore>()
 200326            .AddMemoryStore<ActivityExecutionRecord, MemoryActivityExecutionStore>()
 200327
 200328            // Startup tasks, background tasks, and recurring tasks.
 200329            .AddStartupTask<PopulateRegistriesStartupTask>()
 200330            .AddRecurringTask<TriggerBookmarkQueueRecurringTask>(TimeSpan.FromMinutes(1))
 200331            .AddRecurringTask<PurgeBookmarkQueueRecurringTask>(TimeSpan.FromSeconds(10))
 200332            .AddRecurringTask<RestartInterruptedWorkflowsTask>(TimeSpan.FromMinutes(5)) // Same default as the workflow 
 200333
 200334            // Distributed locking.
 200335            .AddSingleton(DistributedLockProvider)
 200336
 200337            // Workflow providers.
 200338            .AddWorkflowsProvider<ClrWorkflowsProvider>()
 200339
 200340            // UI property handlers.
 200341            .AddScoped<IPropertyUIHandler, DispatcherChannelOptionsProvider>()
 200342
 200343            // Domain handlers.
 200344            .AddCommandHandler<DispatchWorkflowCommandHandler>()
 200345            .AddCommandHandler<DispatchStimulusCommandHandler>()
 200346            .AddCommandHandler<CancelWorkflowsCommandHandler>()
 200347            .AddNotificationHandler<ResumeDispatchWorkflowActivity>()
 200348            .AddNotificationHandler<ResumeBulkDispatchWorkflowActivity>()
 200349            .AddNotificationHandler<ResumeExecuteWorkflowActivity>()
 200350            .AddNotificationHandler<IndexTriggers>()
 200351            .AddNotificationHandler<CancelBackgroundActivities>()
 200352            .AddNotificationHandler<DeleteBookmarks>()
 200353            .AddNotificationHandler<DeleteTriggers>()
 200354            .AddNotificationHandler<DeleteActivityExecutionLogRecords>()
 200355            .AddNotificationHandler<DeleteWorkflowExecutionLogRecords>()
 200356            .AddNotificationHandler<RefreshActivityRegistry>()
 200357            .AddNotificationHandler<SignalBookmarkQueueWorker>()
 200358            .AddNotificationHandler<EvaluateParentLogPersistenceModes>()
 200359            .AddNotificationHandler<CaptureActivityExecutionState>()
 200360            .AddNotificationHandler<ValidateWorkflowRequestHandler>()
 200361
 200362            // Workflow activation strategies.
 200363            .AddScoped<IWorkflowActivationStrategy, SingletonStrategy>()
 200364            .AddScoped<IWorkflowActivationStrategy, CorrelatedSingletonStrategy>()
 200365            .AddScoped<IWorkflowActivationStrategy, CorrelationStrategy>()
 200366            ;
 200367    }
 368}