< 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))]
 20233public class WorkflowRuntimeFeature(IModule module) : FeatureBase(module)
 34{
 36635    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>
 82640    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>
 46745    public Func<IServiceProvider, IWorkflowRuntime> WorkflowRuntime { get; set; } = sp => ActivatorUtilities.CreateInsta
 46
 47    /// <summary>
 48    /// A factory that instantiates an <see cref="IWorkflowDispatcher"/>.
 49    /// </summary>
 40450    public Func<IServiceProvider, IWorkflowDispatcher> WorkflowDispatcher { get; set; } = sp =>
 20251    {
 44152        var decoratedService = ActivatorUtilities.CreateInstance<BackgroundWorkflowDispatcher>(sp);
 44153        return ActivatorUtilities.CreateInstance<ValidatingWorkflowDispatcher>(sp, decoratedService);
 20254    };
 55
 56    /// <summary>
 57    /// A factory that instantiates an <see cref="IStimulusDispatcher"/>.
 58    /// </summary>
 41959    public Func<IServiceProvider, IStimulusDispatcher> StimulusDispatcher { get; set; } = sp => ActivatorUtilities.Creat
 60
 61    /// <summary>
 62    /// A factory that instantiates an <see cref="IWorkflowCancellationDispatcher"/>.
 63    /// </summary>
 41164    public Func<IServiceProvider, IWorkflowCancellationDispatcher> WorkflowCancellationDispatcher { get; set; } = sp => 
 65
 66    /// <summary>
 67    /// A factory that instantiates an <see cref="IBookmarkStore"/>.
 68    /// </summary>
 58669    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>
 58774    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>
 59079    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>
 58184    public Func<IServiceProvider, IWorkflowExecutionLogStore> WorkflowExecutionLogStore { get; set; } = sp => sp.GetRequ
 85
 86    /// <summary>
 87    /// A factory that instantiates an <see cref="IActivityExecutionStore"/>.
 88    /// </summary>
 57289    public Func<IServiceProvider, IActivityExecutionStore> ActivityExecutionLogStore { get; set; } = sp => sp.GetRequire
 90
 91    /// <summary>
 92    /// A factory that instantiates an <see cref="IDistributedLockProvider"/>.
 93    /// </summary>
 57794    public Func<IServiceProvider, IDistributedLockProvider> DistributedLockProvider { get; set; } = _ => new FileDistrib
 95
 96    /// <summary>
 97    /// A factory that instantiates an <see cref="ITaskDispatcher"/>.
 98    /// </summary>
 40499    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>
 923109    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>
 923114    public Func<IServiceProvider, ILogRecordSink<WorkflowExecutionLogRecord>> WorkflowExecutionLogSink { get; set; } = s
 115
 116    /// <summary>
 117    /// A factory that instantiates an <see cref="ICommandHandler"/>.
 118    /// </summary>
 202119    public Func<IServiceProvider, ICommandHandler> DispatchWorkflowCommandHandler { get; set; } = sp => sp.GetRequiredSe
 120
 121    /// <summary>
 122    /// A factory that instantiates an <see cref="IWorkflowResumer"/>.
 123    /// </summary>
 537124    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>
 617129    public Func<IServiceProvider, IBookmarkQueueWorker> BookmarkQueueWorker { get; set; } = sp => sp.GetRequiredService<
 130
 131    /// <summary>
 132    /// A delegate to configure the <see cref="DistributedLockingOptions"/>.
 133    /// </summary>
 577134    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")]
 404140    public Action<WorkflowInboxCleanupOptions> WorkflowInboxCleanupOptions { get; set; } = _ => { };
 141
 142    /// <summary>
 143    /// A delegate to configure the <see cref="WorkflowDispatcherOptions"/>.
 144    /// </summary>
 568145    public Action<WorkflowDispatcherOptions> WorkflowDispatcherOptions { get; set; } = _ => { };
 146
 147    /// <summary>
 148    /// A delegate to configure the <see cref="BookmarkQueuePurgeOptions"/>.
 149    /// </summary>
 404150    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    {
 22175        Workflows.Add<T>();
 22176        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    {
 14185        var workflowTypes = assembly.GetExportedTypes()
 924186            .Where(x => typeof(IWorkflow).IsAssignableFrom(x) && x is { IsAbstract: false, IsInterface: false, IsGeneric
 14187            .ToList();
 188
 910189        foreach (var workflowType in workflowTypes)
 441190            Workflows.Add(workflowType);
 191
 14192        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    {
 202218        Module.AddActivitiesFrom<WorkflowRuntimeFeature>();
 202219        Module.Configure<WorkflowsFeature>(workflows =>
 202220        {
 721221            workflows.CommitStateHandler = sp => sp.GetRequiredService<DefaultCommitStateHandler>();
 404222        });
 223
 202224        Services.Configure<RecurringTaskOptions>(options =>
 202225        {
 11226            options.Schedule.ConfigureTask<TriggerBookmarkQueueRecurringTask>(TimeSpan.FromSeconds(10));
 213227        });
 202228    }
 229
 230    /// <inheritdoc />
 231    public override void Apply()
 232    {
 233        // Options.
 202234        Services.Configure(DistributedLockingOptions);
 202235        Services.Configure(WorkflowInboxCleanupOptions);
 202236        Services.Configure(WorkflowDispatcherOptions);
 202237        Services.Configure(BookmarkQueuePurgeOptions);
 524238        Services.Configure<RuntimeOptions>(options => { options.Workflows = Workflows; });
 202239        Services.Configure<WorkflowDispatcherOptions>(options =>
 202240        {
 164241            options.Channels.AddRange(WorkflowDispatcherChannels.Values);
 366242        });
 243
 202244        Services
 202245            // Core.
 202246            .AddScoped<ITriggerIndexer, TriggerIndexer>()
 202247            .AddScoped<IWorkflowInstanceFactory, WorkflowInstanceFactory>()
 202248            .AddScoped<IWorkflowHostFactory, WorkflowHostFactory>()
 202249            .AddScoped<IBackgroundActivityInvoker, BackgroundActivityInvoker>()
 202250            .AddScoped(WorkflowRuntime)
 202251            .AddScoped(WorkflowDispatcher)
 202252            .AddScoped(StimulusDispatcher)
 202253            .AddScoped(WorkflowCancellationDispatcher)
 202254            .AddScoped(RunTaskDispatcher)
 202255            .AddScoped(ActivityExecutionLogSink)
 202256            .AddScoped(WorkflowExecutionLogSink)
 202257            .AddSingleton(BackgroundActivityScheduler)
 202258            .AddSingleton<RandomLongIdentityGenerator>()
 202259            .AddSingleton<IBookmarkQueueSignaler, BookmarkQueueSignaler>()
 202260            .AddScoped(BookmarkQueueWorker)
 202261            .AddScoped<IBookmarkManager, DefaultBookmarkManager>()
 202262            .AddScoped<IActivityExecutionManager, DefaultActivityExecutionManager>()
 202263            .AddScoped<IActivityExecutionStatsService, ActivityExecutionStatsService>()
 202264            .AddScoped<IActivityExecutionMapper, DefaultActivityExecutionMapper>()
 202265            .AddScoped<IWorkflowDefinitionStorePopulator, DefaultWorkflowDefinitionStorePopulator>()
 202266            .AddScoped<IRegistriesPopulator, DefaultRegistriesPopulator>()
 202267            .AddScoped<IWorkflowDefinitionsRefresher, WorkflowDefinitionsRefresher>()
 202268            .AddScoped<IWorkflowDefinitionsReloader, WorkflowDefinitionsReloader>()
 202269            .AddScoped<IWorkflowRegistry, DefaultWorkflowRegistry>()
 202270            .AddScoped<IWorkflowMatcher, WorkflowMatcher>()
 202271            .AddScoped<IWorkflowInvoker, WorkflowInvoker>()
 202272            .AddScoped<IStimulusSender, StimulusSender>()
 202273            .AddScoped<ITriggerBoundWorkflowService, TriggerBoundWorkflowService>()
 202274            .AddScoped<IBookmarkBoundWorkflowService, BookmarkBoundWorkflowService>()
 202275            .AddScoped<ITaskReporter, TaskReporter>()
 202276            .AddScoped<SynchronousTaskDispatcher>()
 202277            .AddScoped<BackgroundTaskDispatcher>()
 202278            .AddScoped<StoreActivityExecutionLogSink>()
 202279            .AddScoped<StoreWorkflowExecutionLogSink>()
 202280            .AddScoped<DispatchWorkflowCommandHandler>()
 202281            .AddScoped<IEventPublisher, EventPublisher>()
 202282            .AddScoped<IBookmarkUpdater, BookmarkUpdater>()
 202283            .AddScoped<IBookmarksPersister, BookmarksPersister>()
 202284            .AddScoped<IBookmarkResumer, BookmarkResumer>()
 202285            .AddScoped<IBookmarkQueue, StoreBookmarkQueue>()
 202286            .AddScoped(WorkflowResumer)
 202287            .AddScoped<WorkflowResumer>()
 202288            .AddScoped(BookmarkQueueWorker)
 202289            .AddScoped<BookmarkQueueWorker>()
 202290            .AddScoped<ITriggerInvoker, TriggerInvoker>()
 202291            .AddScoped<IWorkflowCanceler, WorkflowCanceler>()
 202292            .AddScoped<IWorkflowCancellationService, WorkflowCancellationService>()
 202293            .AddScoped<IWorkflowActivationStrategyEvaluator, DefaultWorkflowActivationStrategyEvaluator>()
 202294            .AddScoped<IWorkflowStarter, DefaultWorkflowStarter>()
 202295            .AddScoped<IWorkflowRestarter, DefaultWorkflowRestarter>()
 202296            .AddScoped<IBookmarkQueuePurger, DefaultBookmarkQueuePurger>()
 202297            .AddScoped<ILogRecordExtractor<WorkflowExecutionLogRecord>, WorkflowExecutionLogRecordExtractor>()
 202298            .AddScoped<IActivityPropertyLogPersistenceEvaluator, ActivityPropertyLogPersistenceEvaluator>()
 202299            .AddScoped<IBookmarkQueueProcessor, BookmarkQueueProcessor>()
 202300            .AddScoped<DefaultCommitStateHandler>()
 202301            .AddScoped<WorkflowHeartbeatGeneratorFactory>()
 202302
 202303            // Deprecated services.
 202304            .AddScoped<IWorkflowInbox, StimulusProxyWorkflowInbox>()
 202305
 202306            // Stores.
 202307            .AddScoped(BookmarkStore)
 202308            .AddScoped(BookmarkQueueStore)
 202309            .AddScoped(TriggerStore)
 202310            .AddScoped(WorkflowExecutionLogStore)
 202311            .AddScoped(ActivityExecutionLogStore)
 202312
 202313            // Lazy services.
 167314            .AddScoped<Func<IEnumerable<IWorkflowsProvider>>>(sp => sp.GetServices<IWorkflowsProvider>)
 620315            .AddScoped<Func<IEnumerable<IWorkflowMaterializer>>>(sp => sp.GetServices<IWorkflowMaterializer>)
 202316
 202317            // Noop stores.
 202318            .AddScoped<MemoryWorkflowExecutionLogStore>()
 202319            .AddScoped<MemoryActivityExecutionStore>()
 202320
 202321            // Memory stores.
 202322            .AddMemoryStore<StoredBookmark, MemoryBookmarkStore>()
 202323            .AddMemoryStore<StoredTrigger, MemoryTriggerStore>()
 202324            .AddMemoryStore<BookmarkQueueItem, MemoryBookmarkQueueStore>()
 202325            .AddMemoryStore<WorkflowExecutionLogRecord, MemoryWorkflowExecutionLogStore>()
 202326            .AddMemoryStore<ActivityExecutionRecord, MemoryActivityExecutionStore>()
 202327
 202328            // Startup tasks, background tasks, and recurring tasks.
 202329            .AddStartupTask<PopulateRegistriesStartupTask>()
 202330            .AddRecurringTask<TriggerBookmarkQueueRecurringTask>(TimeSpan.FromMinutes(1))
 202331            .AddRecurringTask<PurgeBookmarkQueueRecurringTask>(TimeSpan.FromSeconds(10))
 202332            .AddRecurringTask<RestartInterruptedWorkflowsTask>(TimeSpan.FromMinutes(5)) // Same default as the workflow 
 202333
 202334            // Distributed locking.
 202335            .AddSingleton(DistributedLockProvider)
 202336
 202337            // Workflow definition providers.
 202338            .AddWorkflowDefinitionProvider<ClrWorkflowsProvider>()
 202339
 202340            // UI property handlers.
 202341            .AddScoped<IPropertyUIHandler, DispatcherChannelOptionsProvider>()
 202342
 202343            // Domain handlers.
 202344            .AddCommandHandler<DispatchWorkflowCommandHandler>()
 202345            .AddCommandHandler<DispatchStimulusCommandHandler>()
 202346            .AddCommandHandler<CancelWorkflowsCommandHandler>()
 202347            .AddNotificationHandler<ResumeDispatchWorkflowActivity>()
 202348            .AddNotificationHandler<ResumeBulkDispatchWorkflowActivity>()
 202349            .AddNotificationHandler<ResumeExecuteWorkflowActivity>()
 202350            .AddNotificationHandler<IndexTriggers>()
 202351            .AddNotificationHandler<CancelBackgroundActivities>()
 202352            .AddNotificationHandler<DeleteBookmarks>()
 202353            .AddNotificationHandler<DeleteTriggers>()
 202354            .AddNotificationHandler<DeleteActivityExecutionLogRecords>()
 202355            .AddNotificationHandler<DeleteWorkflowExecutionLogRecords>()
 202356            .AddNotificationHandler<RefreshActivityRegistry>()
 202357            .AddNotificationHandler<SignalBookmarkQueueWorker>()
 202358            .AddNotificationHandler<EvaluateParentLogPersistenceModes>()
 202359            .AddNotificationHandler<CaptureActivityExecutionState>()
 202360            .AddNotificationHandler<ValidateWorkflowRequestHandler>()
 202361
 202362            // Workflow activation strategies.
 202363            .AddScoped<IWorkflowActivationStrategy, SingletonStrategy>()
 202364            .AddScoped<IWorkflowActivationStrategy, CorrelatedSingletonStrategy>()
 202365            .AddScoped<IWorkflowActivationStrategy, CorrelationStrategy>()
 202366            ;
 202367    }
 368}