< 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: 175
Uncovered lines: 10
Coverable lines: 185
Total lines: 357
Line coverage: 94.5%
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))]
 17233public class WorkflowRuntimeFeature(IModule module) : FeatureBase(module)
 34{
 31135    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>
 36640    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>
 40045    public Func<IServiceProvider, IWorkflowRuntime> WorkflowRuntime { get; set; } = sp => ActivatorUtilities.CreateInsta
 46
 47    /// <summary>
 48    /// A factory that instantiates an <see cref="IWorkflowDispatcher"/>.
 49    /// </summary>
 34450    public Func<IServiceProvider, IWorkflowDispatcher> WorkflowDispatcher { get; set; } = sp =>
 17251    {
 32952        var decoratedService = ActivatorUtilities.CreateInstance<BackgroundWorkflowDispatcher>(sp);
 32953        return ActivatorUtilities.CreateInstance<ValidatingWorkflowDispatcher>(sp, decoratedService);
 17254    };
 55
 56    /// <summary>
 57    /// A factory that instantiates an <see cref="IStimulusDispatcher"/>.
 58    /// </summary>
 35059    public Func<IServiceProvider, IStimulusDispatcher> StimulusDispatcher { get; set; } = sp => ActivatorUtilities.Creat
 60
 61    /// <summary>
 62    /// A factory that instantiates an <see cref="IWorkflowCancellationDispatcher"/>.
 63    /// </summary>
 34564    public Func<IServiceProvider, IWorkflowCancellationDispatcher> WorkflowCancellationDispatcher { get; set; } = sp => 
 65
 66    /// <summary>
 67    /// A factory that instantiates an <see cref="IBookmarkStore"/>.
 68    /// </summary>
 50369    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>
 50574    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>
 50379    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>
 49584    public Func<IServiceProvider, IWorkflowExecutionLogStore> WorkflowExecutionLogStore { get; set; } = sp => sp.GetRequ
 85
 86    /// <summary>
 87    /// A factory that instantiates an <see cref="IActivityExecutionStore"/>.
 88    /// </summary>
 48689    public Func<IServiceProvider, IActivityExecutionStore> ActivityExecutionLogStore { get; set; } = sp => sp.GetRequire
 90
 91    /// <summary>
 92    /// A factory that instantiates an <see cref="IDistributedLockProvider"/>.
 93    /// </summary>
 35094    public Func<IServiceProvider, IDistributedLockProvider> DistributedLockProvider { get; set; } = _ => new FileDistrib
 95
 96    /// <summary>
 97    /// A factory that instantiates an <see cref="ITaskDispatcher"/>.
 98    /// </summary>
 34499    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>
 485104    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>
 781109    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>
 781114    public Func<IServiceProvider, ILogRecordSink<WorkflowExecutionLogRecord>> WorkflowExecutionLogSink { get; set; } = s
 115
 116    /// <summary>
 117    /// A factory that instantiates an <see cref="ICommandHandler"/>.
 118    /// </summary>
 172119    public Func<IServiceProvider, ICommandHandler> DispatchWorkflowCommandHandler { get; set; } = sp => sp.GetRequiredSe
 120
 173121    public Func<IServiceProvider, IBookmarkQueueWorker> BookmarkQueueWorker { get; set; } = sp => sp.GetRequiredService<
 122
 123    /// <summary>
 124    /// A delegate to configure the <see cref="DistributedLockingOptions"/>.
 125    /// </summary>
 350126    public Action<DistributedLockingOptions> DistributedLockingOptions { get; set; } = _ => { };
 127
 128    /// <summary>
 129    /// A delegate to configure the <see cref="WorkflowInboxCleanupOptions"/>.
 130    /// </summary>
 131    [Obsolete("Will be removed in a future version")]
 344132    public Action<WorkflowInboxCleanupOptions> WorkflowInboxCleanupOptions { get; set; } = _ => { };
 133
 134    /// <summary>
 135    /// A delegate to configure the <see cref="WorkflowDispatcherOptions"/>.
 136    /// </summary>
 483137    public Action<WorkflowDispatcherOptions> WorkflowDispatcherOptions { get; set; } = _ => { };
 138
 139    /// <summary>
 140    /// A delegate to configure the <see cref="BookmarkQueuePurgeOptions"/>.
 141    /// </summary>
 344142    public Action<BookmarkQueuePurgeOptions> BookmarkQueuePurgeOptions { get; set; } = _ => { };
 143
 144    /// <summary>
 145    /// Enables the workflow inbox cleanup job.
 146    /// </summary>
 147    public WorkflowRuntimeFeature EnableWorkflowInboxCleanupJob()
 148    {
 0149        Services.Configure<WorkflowInboxCleanupOptions>(options => { options.IsEnabled = true; });
 0150        return this;
 151    }
 152
 153    /// <summary>
 154    /// Disables the workflow inbox cleanup job.
 155    /// </summary>
 156    public WorkflowRuntimeFeature DisableWorkflowInboxCleanupJob()
 157    {
 0158        Services.Configure<WorkflowInboxCleanupOptions>(options => { options.IsEnabled = false; });
 0159        return this;
 160    }
 161
 162    /// <summary>
 163    /// Register the specified workflow type.
 164    /// </summary>
 165    public WorkflowRuntimeFeature AddWorkflow<T>() where T : IWorkflow
 166    {
 9167        Workflows.Add<T>();
 9168        return this;
 169    }
 170
 171    /// <summary>
 172    /// Register all workflows in the specified assembly.
 173    /// </summary>
 174    [RequiresUnreferencedCode("The assembly is required to be referenced.")]
 175    public WorkflowRuntimeFeature AddWorkflowsFrom(Assembly assembly)
 176    {
 2177        var workflowTypes = assembly.GetExportedTypes()
 101178            .Where(x => typeof(IWorkflow).IsAssignableFrom(x) && x is { IsAbstract: false, IsInterface: false, IsGeneric
 2179            .ToList();
 180
 102181        foreach (var workflowType in workflowTypes)
 49182            Workflows.Add(workflowType);
 183
 2184        return this;
 185    }
 186
 187    /// <summary>
 188    /// Adds a dispatcher channel.
 189    /// </summary>
 190    public WorkflowRuntimeFeature AddDispatcherChannel(string channel)
 191    {
 0192        return AddDispatcherChannel(new DispatcherChannel
 0193        {
 0194            Name = channel
 0195        });
 196    }
 197
 198    /// <summary>
 199    /// Adds a dispatcher channel.
 200    /// </summary>
 201    public WorkflowRuntimeFeature AddDispatcherChannel(DispatcherChannel channel)
 202    {
 0203        WorkflowDispatcherChannels[channel.Name] = channel;
 0204        return this;
 205    }
 206
 207    /// <inheritdoc />
 208    public override void Configure()
 209    {
 172210        Module.AddActivitiesFrom<WorkflowRuntimeFeature>();
 172211        Module.Configure<WorkflowsFeature>(workflows =>
 172212        {
 609213            workflows.CommitStateHandler = sp => sp.GetRequiredService<DefaultCommitStateHandler>();
 344214        });
 215
 172216        Services.Configure<RecurringTaskOptions>(options =>
 172217        {
 5218            options.Schedule.ConfigureTask<TriggerBookmarkQueueRecurringTask>(TimeSpan.FromSeconds(10));
 177219        });
 172220    }
 221
 222    /// <inheritdoc />
 223    public override void Apply()
 224    {
 225        // Options.
 172226        Services.Configure(DistributedLockingOptions);
 172227        Services.Configure(WorkflowInboxCleanupOptions);
 172228        Services.Configure(WorkflowDispatcherOptions);
 172229        Services.Configure(BookmarkQueuePurgeOptions);
 444230        Services.Configure<RuntimeOptions>(options => { options.Workflows = Workflows; });
 172231        Services.Configure<WorkflowDispatcherOptions>(options =>
 172232        {
 139233            options.Channels.AddRange(WorkflowDispatcherChannels.Values);
 311234        });
 235
 172236        Services
 172237            // Core.
 172238            .AddScoped<ITriggerIndexer, TriggerIndexer>()
 172239            .AddScoped<IWorkflowInstanceFactory, WorkflowInstanceFactory>()
 172240            .AddScoped<IWorkflowHostFactory, WorkflowHostFactory>()
 172241            .AddScoped<IBackgroundActivityInvoker, BackgroundActivityInvoker>()
 172242            .AddScoped(WorkflowRuntime)
 172243            .AddScoped(WorkflowDispatcher)
 172244            .AddScoped(StimulusDispatcher)
 172245            .AddScoped(WorkflowCancellationDispatcher)
 172246            .AddScoped(RunTaskDispatcher)
 172247            .AddScoped(ActivityExecutionLogSink)
 172248            .AddScoped(WorkflowExecutionLogSink)
 172249            .AddSingleton(BackgroundActivityScheduler)
 172250            .AddSingleton<RandomLongIdentityGenerator>()
 172251            .AddSingleton<IBookmarkQueueSignaler, BookmarkQueueSignaler>()
 172252            .AddScoped<IBookmarkQueueWorker, BookmarkQueueWorker>()
 172253            .AddScoped<IBookmarkManager, DefaultBookmarkManager>()
 172254            .AddScoped<IActivityExecutionManager, DefaultActivityExecutionManager>()
 172255            .AddScoped<IActivityExecutionStatsService, ActivityExecutionStatsService>()
 172256            .AddScoped<IActivityExecutionMapper, DefaultActivityExecutionMapper>()
 172257            .AddScoped<IWorkflowDefinitionStorePopulator, DefaultWorkflowDefinitionStorePopulator>()
 172258            .AddScoped<IRegistriesPopulator, DefaultRegistriesPopulator>()
 172259            .AddScoped<IWorkflowDefinitionsRefresher, WorkflowDefinitionsRefresher>()
 172260            .AddScoped<IWorkflowDefinitionsReloader, WorkflowDefinitionsReloader>()
 172261            .AddScoped<IWorkflowRegistry, DefaultWorkflowRegistry>()
 172262            .AddScoped<IWorkflowMatcher, WorkflowMatcher>()
 172263            .AddScoped<IWorkflowInvoker, WorkflowInvoker>()
 172264            .AddScoped<IStimulusSender, StimulusSender>()
 172265            .AddScoped<ITriggerBoundWorkflowService, TriggerBoundWorkflowService>()
 172266            .AddScoped<IBookmarkBoundWorkflowService, BookmarkBoundWorkflowService>()
 172267            .AddScoped<ITaskReporter, TaskReporter>()
 172268            .AddScoped<SynchronousTaskDispatcher>()
 172269            .AddScoped<BackgroundTaskDispatcher>()
 172270            .AddScoped<StoreActivityExecutionLogSink>()
 172271            .AddScoped<StoreWorkflowExecutionLogSink>()
 172272            .AddScoped<DispatchWorkflowCommandHandler>()
 172273            .AddScoped<IEventPublisher, EventPublisher>()
 172274            .AddScoped<IBookmarkUpdater, BookmarkUpdater>()
 172275            .AddScoped<IBookmarksPersister, BookmarksPersister>()
 172276            .AddScoped<IBookmarkResumer, BookmarkResumer>()
 172277            .AddScoped<IBookmarkQueue, StoreBookmarkQueue>()
 172278            .AddScoped<IWorkflowResumer, WorkflowResumer>()
 172279            .AddScoped<ITriggerInvoker, TriggerInvoker>()
 172280            .AddScoped<IWorkflowCanceler, WorkflowCanceler>()
 172281            .AddScoped<IWorkflowCancellationService, WorkflowCancellationService>()
 172282            .AddScoped<IWorkflowActivationStrategyEvaluator, DefaultWorkflowActivationStrategyEvaluator>()
 172283            .AddScoped<IWorkflowStarter, DefaultWorkflowStarter>()
 172284            .AddScoped<IWorkflowRestarter, DefaultWorkflowRestarter>()
 172285            .AddScoped<IBookmarkQueuePurger, DefaultBookmarkQueuePurger>()
 172286            .AddScoped<ILogRecordExtractor<WorkflowExecutionLogRecord>, WorkflowExecutionLogRecordExtractor>()
 172287            .AddScoped<IActivityPropertyLogPersistenceEvaluator, ActivityPropertyLogPersistenceEvaluator>()
 172288            .AddScoped<IBookmarkQueueProcessor, BookmarkQueueProcessor>()
 172289            .AddScoped<DefaultCommitStateHandler>()
 172290            .AddScoped<WorkflowHeartbeatGeneratorFactory>()
 172291
 172292            // Deprecated services.
 172293            .AddScoped<IWorkflowInbox, StimulusProxyWorkflowInbox>()
 172294
 172295            // Stores.
 172296            .AddScoped(BookmarkStore)
 172297            .AddScoped(BookmarkQueueStore)
 172298            .AddScoped(TriggerStore)
 172299            .AddScoped(WorkflowExecutionLogStore)
 172300            .AddScoped(ActivityExecutionLogStore)
 172301
 172302            // Lazy services.
 143303            .AddScoped<Func<IEnumerable<IWorkflowsProvider>>>(sp => sp.GetServices<IWorkflowsProvider>)
 482304            .AddScoped<Func<IEnumerable<IWorkflowMaterializer>>>(sp => sp.GetServices<IWorkflowMaterializer>)
 172305
 172306            // Noop stores.
 172307            .AddScoped<MemoryWorkflowExecutionLogStore>()
 172308            .AddScoped<MemoryActivityExecutionStore>()
 172309
 172310            // Memory stores.
 172311            .AddMemoryStore<StoredBookmark, MemoryBookmarkStore>()
 172312            .AddMemoryStore<StoredTrigger, MemoryTriggerStore>()
 172313            .AddMemoryStore<BookmarkQueueItem, MemoryBookmarkQueueStore>()
 172314            .AddMemoryStore<WorkflowExecutionLogRecord, MemoryWorkflowExecutionLogStore>()
 172315            .AddMemoryStore<ActivityExecutionRecord, MemoryActivityExecutionStore>()
 172316
 172317            // Startup tasks, background tasks, and recurring tasks.
 172318            .AddStartupTask<PopulateRegistriesStartupTask>()
 172319            .AddRecurringTask<TriggerBookmarkQueueRecurringTask>(TimeSpan.FromMinutes(1))
 172320            .AddRecurringTask<PurgeBookmarkQueueRecurringTask>(TimeSpan.FromSeconds(10))
 172321            .AddRecurringTask<RestartInterruptedWorkflowsTask>(TimeSpan.FromMinutes(5)) // Same default as the workflow 
 172322
 172323            // Distributed locking.
 172324            .AddSingleton(DistributedLockProvider)
 172325
 172326            // Workflow definition providers.
 172327            .AddWorkflowDefinitionProvider<ClrWorkflowsProvider>()
 172328
 172329            // UI property handlers.
 172330            .AddScoped<IPropertyUIHandler, DispatcherChannelOptionsProvider>()
 172331
 172332            // Domain handlers.
 172333            .AddCommandHandler<DispatchWorkflowCommandHandler>()
 172334            .AddCommandHandler<DispatchStimulusCommandHandler>()
 172335            .AddCommandHandler<CancelWorkflowsCommandHandler>()
 172336            .AddNotificationHandler<ResumeDispatchWorkflowActivity>()
 172337            .AddNotificationHandler<ResumeBulkDispatchWorkflowActivity>()
 172338            .AddNotificationHandler<ResumeExecuteWorkflowActivity>()
 172339            .AddNotificationHandler<IndexTriggers>()
 172340            .AddNotificationHandler<CancelBackgroundActivities>()
 172341            .AddNotificationHandler<DeleteBookmarks>()
 172342            .AddNotificationHandler<DeleteTriggers>()
 172343            .AddNotificationHandler<DeleteActivityExecutionLogRecords>()
 172344            .AddNotificationHandler<DeleteWorkflowExecutionLogRecords>()
 172345            .AddNotificationHandler<RefreshActivityRegistry>()
 172346            .AddNotificationHandler<SignalBookmarkQueueWorker>()
 172347            .AddNotificationHandler<EvaluateParentLogPersistenceModes>()
 172348            .AddNotificationHandler<CaptureActivityExecutionState>()
 172349            .AddNotificationHandler<ValidateWorkflowRequestHandler>()
 172350
 172351            // Workflow activation strategies.
 172352            .AddScoped<IWorkflowActivationStrategy, SingletonStrategy>()
 172353            .AddScoped<IWorkflowActivationStrategy, CorrelatedSingletonStrategy>()
 172354            .AddScoped<IWorkflowActivationStrategy, CorrelationStrategy>()
 172355            ;
 172356    }
 357}