< 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: 239
Uncovered lines: 13
Coverable lines: 252
Total lines: 480
Line coverage: 94.8%
Branch coverage
100%
Covered branches: 14
Total branches: 14
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
get_WorkflowDispatcherChannels()100%11100%
get_Workflows()100%11100%
get_WorkflowTypes()100%11100%
get_WorkflowRuntime()100%11100%
get_WorkflowDispatcher()100%11100%
get_StimulusDispatcher()100%11100%
get_WorkflowCancellationDispatcher()100%11100%
get_WorkflowDispatchOutboxStore()100%11100%
get_BookmarkStore()100%11100%
get_BookmarkQueueStore()100%11100%
get_BookmarkQueueDeadLetterStore()100%11100%
get_TriggerStore()100%11100%
get_WorkflowExecutionLogStore()100%11100%
get_ActivityExecutionLogStore()100%11100%
get_DistributedLockProvider()100%11100%
get_RunTaskDispatcher()100%11100%
get_BackgroundActivityScheduler()100%11100%
get_ActivityExecutionLogSink()100%11100%
get_WorkflowExecutionLogSink()100%11100%
get_DispatchWorkflowCommandHandler()100%11100%
get_WorkflowResumer()100%11100%
get_BookmarkQueueWorker()100%11100%
get_DistributedLockingOptions()100%11100%
get_WorkflowInboxCleanupOptions()100%11100%
get_WorkflowDispatcherOptions()100%11100%
get_BookmarkQueuePurgeOptions()100%11100%
EnableWorkflowInboxCleanupJob()100%210%
DisableWorkflowInboxCleanupJob()100%210%
AddWorkflow()100%11100%
AddWorkflow(...)100%11100%
AddWorkflowsFrom(...)100%22100%
AddDispatcherChannel(...)100%210%
AddDispatcherChannel(...)100%210%
Configure()100%11100%
get_GracefulShutdown()100%11100%
Apply()100%11100%
RegisterWorkflowTypeAliases(...)100%11100%
GetRegisteredWorkflowTypes()100%11100%
TryResolveWorkflowType(...)100%201262.5%

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;
 4using Elsa.Common.DistributedHosting;
 5using Elsa.Common.Features;
 6using Elsa.Common.RecurringTasks;
 7using Elsa.Extensions;
 8using Elsa.Features.Abstractions;
 9using Elsa.Features.Attributes;
 10using Elsa.Features.Services;
 11using Elsa.Mediator.Contracts;
 12using Elsa.Workflows.Features;
 13using Elsa.Workflows.Management;
 14using Elsa.Workflows.Management.Contracts;
 15using Elsa.Workflows.Management.Services;
 16using Elsa.Workflows.Options;
 17using Elsa.Workflows.Runtime.ActivationValidators;
 18using Elsa.Workflows.Runtime.Bookmarks;
 19using Elsa.Workflows.Runtime.Discovery;
 20using Elsa.Workflows.Runtime.Entities;
 21using Elsa.Workflows.Runtime.Handlers;
 22using Elsa.Workflows.Runtime.Models;
 23using Elsa.Workflows.Runtime.Options;
 24using Elsa.Workflows.Runtime.Providers;
 25using Elsa.Workflows.Runtime.Stimuli;
 26using Elsa.Workflows.Runtime.Stores;
 27using Elsa.Workflows.Runtime.Tasks;
 28using Elsa.Workflows.Runtime.UIHints;
 29using Medallion.Threading;
 30using Medallion.Threading.FileSystem;
 31using Microsoft.Extensions.DependencyInjection;
 32using Microsoft.Extensions.DependencyInjection.Extensions;
 33using Microsoft.Extensions.Options;
 34using Elsa.Common.Serialization;
 35
 36namespace Elsa.Workflows.Runtime.Features;
 37
 38/// <summary>
 39/// Installs and configures workflow runtime features.
 40/// </summary>
 41[DependsOn(typeof(SystemClockFeature))]
 42[DependsOn(typeof(WorkflowsFeature))]
 28043public class WorkflowRuntimeFeature(IModule module) : FeatureBase(module)
 44{
 47245    private IDictionary<string, DispatcherChannel> WorkflowDispatcherChannels { get; set; } = new Dictionary<string, Dis
 46
 47    /// <summary>
 48    /// A list of workflow builders configured during application startup.
 49    /// </summary>
 95050    public IDictionary<string, Func<IServiceProvider, ValueTask<IWorkflow>>> Workflows { get; set; } = new Dictionary<st
 74051    private ISet<Type> WorkflowTypes { get; } = new HashSet<Type>();
 52
 53    /// <summary>
 54    /// A factory that instantiates a concrete <see cref="IWorkflowRuntime"/>.
 55    /// </summary>
 71656    public Func<IServiceProvider, IWorkflowRuntime> WorkflowRuntime { get; set; } = sp => ActivatorUtilities.CreateInsta
 57
 58    /// <summary>
 59    /// A factory that instantiates an <see cref="IWorkflowDispatcher"/>.
 60    /// </summary>
 54261    public Func<IServiceProvider, IWorkflowDispatcher> WorkflowDispatcher { get; set; } = sp =>
 28062    {
 49563        var decoratedService = ActivatorUtilities.CreateInstance<BackgroundWorkflowDispatcher>(sp);
 49564        var transactionalService = ActivatorUtilities.CreateInstance<TransactionalWorkflowDispatcher>(sp, decoratedServi
 49565        return ActivatorUtilities.CreateInstance<ValidatingWorkflowDispatcher>(sp, transactionalService);
 28066    };
 67
 68    /// <summary>
 69    /// A factory that instantiates an <see cref="IStimulusDispatcher"/>.
 70    /// </summary>
 55371    public Func<IServiceProvider, IStimulusDispatcher> StimulusDispatcher { get; set; } = sp => ActivatorUtilities.Creat
 72
 73    /// <summary>
 74    /// A factory that instantiates an <see cref="IWorkflowCancellationDispatcher"/>.
 75    /// </summary>
 54576    public Func<IServiceProvider, IWorkflowCancellationDispatcher> WorkflowCancellationDispatcher { get; set; } = sp => 
 77
 78    /// <summary>
 79    /// A factory that instantiates an <see cref="IWorkflowDispatchOutboxStore"/>.
 80    /// </summary>
 54281    public Func<IServiceProvider, IWorkflowDispatchOutboxStore> WorkflowDispatchOutboxStore { get; set; } = sp => Activa
 82
 83    /// <summary>
 84    /// A factory that instantiates an <see cref="IBookmarkStore"/>.
 85    /// </summary>
 95886    public Func<IServiceProvider, IBookmarkStore> BookmarkStore { get; set; } = sp => sp.GetRequiredService<MemoryBookma
 87
 88    /// <summary>
 89    /// A factory that instantiates an <see cref="IBookmarkQueueStore"/>.
 90    /// </summary>
 95891    public Func<IServiceProvider, IBookmarkQueueStore> BookmarkQueueStore { get; set; } = sp => sp.GetRequiredService<Me
 92
 93    /// <summary>
 94    /// A factory that instantiates an <see cref="IBookmarkQueueDeadLetterStore"/>.
 95    /// </summary>
 74696    public Func<IServiceProvider, IBookmarkQueueDeadLetterStore> BookmarkQueueDeadLetterStore { get; set; } = sp => sp.G
 97
 98    /// <summary>
 99    /// A factory that instantiates an <see cref="ITriggerStore"/>.
 100    /// </summary>
 842101    public Func<IServiceProvider, ITriggerStore> TriggerStore { get; set; } = sp => sp.GetRequiredService<MemoryTriggerS
 102
 103    /// <summary>
 104    /// A factory that instantiates an <see cref="IWorkflowExecutionLogStore"/>.
 105    /// </summary>
 844106    public Func<IServiceProvider, IWorkflowExecutionLogStore> WorkflowExecutionLogStore { get; set; } = sp => sp.GetRequ
 107
 108    /// <summary>
 109    /// A factory that instantiates an <see cref="IActivityExecutionStore"/>.
 110    /// </summary>
 831111    public Func<IServiceProvider, IActivityExecutionStore> ActivityExecutionLogStore { get; set; } = sp => sp.GetRequire
 112
 113    /// <summary>
 114    /// A factory that instantiates an <see cref="IDistributedLockProvider"/>.
 115    /// </summary>
 750116    public Func<IServiceProvider, IDistributedLockProvider> DistributedLockProvider { get; set; } = _ => new FileDistrib
 117
 118    /// <summary>
 119    /// A factory that instantiates an <see cref="ITaskDispatcher"/>.
 120    /// </summary>
 542121    public Func<IServiceProvider, ITaskDispatcher> RunTaskDispatcher { get; set; } = sp => sp.GetRequiredService<Backgro
 122
 123    /// <summary>
 124    /// A factory that instantiates an <see cref="IBackgroundActivityScheduler"/>.
 125    /// </summary>
 750126    public Func<IServiceProvider, IBackgroundActivityScheduler> BackgroundActivityScheduler { get; set; } = sp => Activa
 127
 128    /// <summary>
 129    /// A factory that instantiates a log record sink for an <see cref="ActivityExecutionRecord"/>.
 130    /// </summary>
 1078131    public Func<IServiceProvider, ILogRecordSink<ActivityExecutionRecord>> ActivityExecutionLogSink { get; set; } = sp =
 132
 133    /// <summary>
 134    /// A factory that instantiates a log record sink for an <see cref="WorkflowExecutionLogRecord"/>.
 135    /// </summary>
 1078136    public Func<IServiceProvider, ILogRecordSink<WorkflowExecutionLogRecord>> WorkflowExecutionLogSink { get; set; } = s
 137
 138    /// <summary>
 139    /// A factory that instantiates an <see cref="ICommandHandler"/>.
 140    /// </summary>
 280141    public Func<IServiceProvider, ICommandHandler> DispatchWorkflowCommandHandler { get; set; } = sp => sp.GetRequiredSe
 142
 143    /// <summary>
 144    /// A factory that instantiates an <see cref="IWorkflowResumer"/>.
 145    /// </summary>
 937146    public Func<IServiceProvider, IWorkflowResumer> WorkflowResumer { get; set; } = sp => sp.GetRequiredService<Workflow
 147
 148    /// <summary>
 149    /// A factory that instantiates an <see cref="IBookmarkQueueWorker"/>.
 150    /// </summary>
 893151    public Func<IServiceProvider, IBookmarkQueueWorker> BookmarkQueueWorker { get; set; } = sp => sp.GetRequiredService<
 152
 153    /// <summary>
 154    /// A delegate to configure the <see cref="DistributedLockingOptions"/>.
 155    /// </summary>
 753156    public Action<DistributedLockingOptions> DistributedLockingOptions { get; set; } = _ => { };
 157
 158    /// <summary>
 159    /// A delegate to configure the <see cref="WorkflowInboxCleanupOptions"/>.
 160    /// </summary>
 161    [Obsolete("Will be removed in a future version")]
 542162    public Action<WorkflowInboxCleanupOptions> WorkflowInboxCleanupOptions { get; set; } = _ => { };
 163
 164    /// <summary>
 165    /// A delegate to configure the <see cref="WorkflowDispatcherOptions"/>.
 166    /// </summary>
 734167    public Action<WorkflowDispatcherOptions> WorkflowDispatcherOptions { get; set; } = _ => { };
 168
 169    /// <summary>
 170    /// A delegate to configure the <see cref="BookmarkQueuePurgeOptions"/>.
 171    /// </summary>
 543172    public Action<BookmarkQueuePurgeOptions> BookmarkQueuePurgeOptions { get; set; } = _ => { };
 173
 174    /// <summary>
 175    /// Enables the workflow inbox cleanup job.
 176    /// </summary>
 177    public WorkflowRuntimeFeature EnableWorkflowInboxCleanupJob()
 178    {
 0179        Services.Configure<WorkflowInboxCleanupOptions>(options => { options.IsEnabled = true; });
 0180        return this;
 181    }
 182
 183    /// <summary>
 184    /// Disables the workflow inbox cleanup job.
 185    /// </summary>
 186    public WorkflowRuntimeFeature DisableWorkflowInboxCleanupJob()
 187    {
 0188        Services.Configure<WorkflowInboxCleanupOptions>(options => { options.IsEnabled = false; });
 0189        return this;
 190    }
 191
 192    /// <summary>
 193    /// Register the specified workflow type.
 194    /// </summary>
 195    public WorkflowRuntimeFeature AddWorkflow<T>() where T : IWorkflow
 196    {
 28197        AddWorkflow(typeof(T));
 28198        return this;
 199    }
 200
 201    /// <summary>
 202    /// Register the specified workflow type.
 203    /// </summary>
 204    public WorkflowRuntimeFeature AddWorkflow(Type workflowType)
 205    {
 226206        Workflows.Add(workflowType);
 222207        WorkflowTypes.Add(workflowType);
 222208        return this;
 209    }
 210
 211    /// <summary>
 212    /// Register all workflows in the specified assembly.
 213    /// </summary>
 214    [RequiresUnreferencedCode("The assembly is required to be referenced.")]
 215    public WorkflowRuntimeFeature AddWorkflowsFrom(Assembly assembly)
 216    {
 396217        foreach (var workflowType in WorkflowTypeScanner.GetWorkflowTypes(assembly))
 192218            AddWorkflow(workflowType);
 219
 6220        return this;
 221    }
 222
 223    /// <summary>
 224    /// Adds a dispatcher channel.
 225    /// </summary>
 226    public WorkflowRuntimeFeature AddDispatcherChannel(string channel)
 227    {
 0228        return AddDispatcherChannel(new DispatcherChannel
 0229        {
 0230            Name = channel
 0231        });
 232    }
 233
 234    /// <summary>
 235    /// Adds a dispatcher channel.
 236    /// </summary>
 237    public WorkflowRuntimeFeature AddDispatcherChannel(DispatcherChannel channel)
 238    {
 0239        WorkflowDispatcherChannels[channel.Name] = channel;
 0240        return this;
 241    }
 242
 243    /// <inheritdoc />
 244    public override void Configure()
 245    {
 262246        Module.AddActivitiesFrom<WorkflowRuntimeFeature>();
 262247        Module.Configure<WorkflowsFeature>(workflows =>
 262248        {
 262249            // ExecutionCycleAwareCommitStateHandler decorates DefaultCommitStateHandler â€” disposes the execution cycle 
 262250            // commit so the drain orchestrator's await-disposed sequencing can land its Interrupted write last.
 798251            workflows.CommitStateHandler = sp => sp.GetRequiredService<Elsa.Workflows.Runtime.Services.ExecutionCycleAwa
 524252        });
 253
 262254        Services.Configure<RecurringTaskOptions>(options =>
 262255        {
 86256            options.Schedule.ConfigureTask<TriggerBookmarkQueueRecurringTask>(TimeSpan.FromSeconds(10));
 348257        });
 262258    }
 259
 260    /// <inheritdoc />
 261    /// <summary>
 262    /// Callback that tunes the graceful-shutdown machinery (drain deadline, per-source pause timeout, stimulus-queue ba
 263    /// pause-persistence policy). Applied when <see cref="Apply"/> binds <see cref="GracefulShutdownOptions"/>.
 264    /// </summary>
 267265    public Action<GracefulShutdownOptions>? GracefulShutdown { get; set; }
 266
 267    public override void Apply()
 268    {
 269        // Options.
 262270        Services.Configure(DistributedLockingOptions);
 262271        Services.Configure(WorkflowInboxCleanupOptions);
 262272        Services.Configure(WorkflowDispatcherOptions);
 262273        Services.Configure(BookmarkQueuePurgeOptions);
 262274        Services.Configure<SerializationTypeOptions>(RegisterWorkflowTypeAliases);
 648275        Services.Configure<RuntimeOptions>(options => { options.Workflows = Workflows; });
 262276        Services.Configure<WorkflowDispatcherOptions>(options =>
 262277        {
 192278            options.Channels.AddRange(WorkflowDispatcherChannels.Values);
 454279        });
 262280        Services.AddGracefulShutdownOptions(GracefulShutdown);
 281
 282        // Graceful-shutdown core (US1 â€” quiescence machinery).
 262283        Services
 96284            .AddSingleton<IQuiescenceSignal>(sp => new Elsa.Workflows.Runtime.Services.QuiescenceSignal(
 96285                sp.GetRequiredService<IOptions<GracefulShutdownOptions>>(),
 96286                sp.GetRequiredService<ISystemClock>(),
 96287                sp.GetRequiredService<IExecutionCycleRegistry>(),
 96288                sp.GetRequiredService<IServiceScopeFactory>()))
 262289            .AddSingleton<IIngressSourceRegistry, Elsa.Workflows.Runtime.Services.IngressSourceRegistry>()
 262290            .AddSingleton<IExecutionCycleRegistry, Elsa.Workflows.Runtime.Services.ExecutionCycleRegistry>()
 262291            // Lazy collection breaks the otherwise-circular DI chain QuiescenceSignal â†’ IExecutionCycleRegistry â†’
 262292            // IIngressSourceRegistry â†’ IEnumerable<IIngressSource> â†’ IQuiescenceSignal. Adapters take a direct
 262293            // IQuiescenceSignal dependency; the registry materializes the collection on first read.
 178294            .AddSingleton(sp => new Lazy<IEnumerable<IIngressSource>>(sp.GetServices<IIngressSource>))
 262295            // Drain orchestrator + hosted service (US1). See FR-029 / R5 â€” heartbeat must outlive drain.
 262296            .AddSingleton<IDrainOrchestrator, Elsa.Workflows.Runtime.Services.DrainOrchestrator>()
 262297            .AddHostedService<Elsa.Workflows.Runtime.HostedServices.DrainOrchestratorHostedService>()
 262298            // Domain service that backs all runtime-admin transports (US2). Encapsulates the audit-on-effective-
 262299            // transition rule (SC-007) so transports stay thin. Scoped because INotificationSender is scoped.
 262300            .AddScoped<IWorkflowRuntimeAdminService, Elsa.Workflows.Runtime.Services.WorkflowRuntimeAdminService>()
 262301            // Interrupted-workflow recovery on shell activation (US3). Disjoint from the timeout-based
 262302            // RestartInterruptedWorkflowsTask: filter is SubStatus = Interrupted; that task's filter is IsExecuting=tru
 262303            .AddScoped<IInterruptedRecoveryScanner, Elsa.Workflows.Runtime.Services.InterruptedRecoveryScanner>()
 262304            .AddStartupTask<Elsa.Workflows.Runtime.StartupTasks.RecoverInterruptedWorkflowsStartupTask>()
 262305            // Internal bookmark-queue processor surfaced as an ingress source for diagnostic visibility (FR-006).
 262306            // Pause behavior is enforced inside BookmarkQueueProcessor via IQuiescenceSignal (FR-024).
 262307            .AddSingleton<IIngressSource, Elsa.Workflows.Runtime.IngressSources.InternalBookmarkQueueIngressSource>()
 262308            // Re-applies persisted pause state on activation when PausePersistence = AcrossReactivations (FR-028).
 262309            .AddStartupTask<Elsa.Workflows.Runtime.StartupTasks.InitializePauseStateStartupTask>();
 310
 262311        Services
 262312            // Core.
 262313            .AddScoped<ITriggerIndexer, TriggerIndexer>()
 262314            .AddScoped<IWorkflowInstanceFactory, WorkflowInstanceFactory>()
 262315            .AddScoped<IWorkflowHostFactory, WorkflowHostFactory>()
 262316            .AddScoped<IBackgroundActivityInvoker, BackgroundActivityInvoker>()
 262317            .AddScoped(WorkflowRuntime)
 262318            .AddScoped(WorkflowDispatcher)
 262319            .AddScoped(StimulusDispatcher)
 262320            .AddScoped(WorkflowCancellationDispatcher)
 262321            .AddScoped(RunTaskDispatcher)
 262322            .AddScoped(ActivityExecutionLogSink)
 262323            .AddScoped(WorkflowExecutionLogSink)
 262324            .AddSingleton(BackgroundActivityScheduler)
 262325            .AddSingleton<RandomLongIdentityGenerator>()
 262326            .AddSingleton<IBookmarkQueueSignaler, BookmarkQueueSignaler>()
 262327            .AddScoped(BookmarkQueueWorker)
 262328            .AddScoped<IBookmarkManager, DefaultBookmarkManager>()
 262329            .AddScoped<IActivityExecutionManager, DefaultActivityExecutionManager>()
 262330            .AddScoped<IActivityExecutionStatsService, ActivityExecutionStatsService>()
 262331            .AddScoped<IActivityExecutionMapper, DefaultActivityExecutionMapper>()
 262332            .AddScoped<IWorkflowDefinitionStorePopulator, DefaultWorkflowDefinitionStorePopulator>()
 262333            .AddScoped<IRegistriesPopulator, DefaultRegistriesPopulator>()
 262334            .AddScoped<IWorkflowDefinitionsRefresher, WorkflowDefinitionsRefresher>()
 262335            .AddScoped<IWorkflowDefinitionsReloader, WorkflowDefinitionsReloader>()
 262336            .AddScoped<IWorkflowRegistry, DefaultWorkflowRegistry>()
 262337            .AddScoped<IWorkflowMatcher, WorkflowMatcher>()
 262338            .AddScoped<IWorkflowInvoker, WorkflowInvoker>()
 262339            .AddScoped<IStimulusSender, StimulusSender>()
 262340            .AddScoped<ITriggerBoundWorkflowService, TriggerBoundWorkflowService>()
 262341            .AddScoped<IBookmarkBoundWorkflowService, BookmarkBoundWorkflowService>()
 262342            .AddScoped<ITaskReporter, TaskReporter>()
 262343            .AddScoped<SynchronousTaskDispatcher>()
 262344            .AddScoped<BackgroundTaskDispatcher>()
 262345            .AddScoped<StoreActivityExecutionLogSink>()
 262346            .AddScoped<StoreWorkflowExecutionLogSink>()
 262347            .AddScoped<DispatchWorkflowCommandHandler>()
 262348            .AddScoped<IEventPublisher, EventPublisher>()
 262349            .AddScoped<IBookmarkUpdater, BookmarkUpdater>()
 262350            .AddScoped<IBookmarksPersister, BookmarksPersister>()
 262351            .AddScoped<IBookmarkResumer, BookmarkResumer>()
 262352            .AddScoped<IBookmarkQueue, StoreBookmarkQueue>()
 262353            .AddScoped<IBookmarkQueueDeadLetterManager, BookmarkQueueDeadLetterManager>()
 262354            .AddScoped(WorkflowResumer)
 262355            .AddScoped<WorkflowResumer>()
 262356            .AddScoped(BookmarkQueueWorker)
 262357            .AddScoped<BookmarkQueueWorker>()
 262358            .AddScoped<ITriggerInvoker, TriggerInvoker>()
 262359            .AddScoped<IWorkflowCanceler, WorkflowCanceler>()
 262360            .AddScoped<IWorkflowCancellationService, WorkflowCancellationService>()
 262361            .AddScoped<IWorkflowActivationStrategyEvaluator, DefaultWorkflowActivationStrategyEvaluator>()
 262362            .AddScoped<IWorkflowStarter, DefaultWorkflowStarter>()
 262363            .AddScoped<IWorkflowRestarter, DefaultWorkflowRestarter>()
 262364            .AddScoped<IBookmarkQueuePurger, DefaultBookmarkQueuePurger>()
 262365            .AddSingleton<IWorkflowDispatchOutboxAccessor, WorkflowDispatchOutboxAccessor>()
 262366            .AddScoped<ILogRecordExtractor<WorkflowExecutionLogRecord>, WorkflowExecutionLogRecordExtractor>()
 262367            .AddScoped<IActivityPropertyLogPersistenceEvaluator, ActivityPropertyLogPersistenceEvaluator>()
 262368            .AddScoped<IBookmarkQueueProcessor, BookmarkQueueProcessor>()
 262369            .AddScoped<WorkflowCommitNotificationBuffer>()
 536370            .AddScoped<IWorkflowCommitNotificationBuffer>(sp => sp.GetRequiredService<WorkflowCommitNotificationBuffer>(
 262371            .AddScoped<INotificationSender, WorkflowCommitNotificationSender>()
 262372            .AddScoped<IWorkflowCommitTransaction, NoopWorkflowCommitTransaction>()
 262373            .AddScoped<DefaultCommitStateHandler>()
 262374            .AddScoped<Elsa.Workflows.Runtime.Services.ExecutionCycleAwareCommitStateHandler>()
 262375            .AddScoped<WorkflowHeartbeatGeneratorFactory>()
 262376
 262377            // Deprecated services.
 262378            .AddScoped<IWorkflowInbox, StimulusProxyWorkflowInbox>()
 262379
 262380            // Stores.
 262381            .AddScoped(BookmarkStore)
 262382            .AddScoped(BookmarkQueueStore)
 262383            .AddScoped(BookmarkQueueDeadLetterStore)
 262384            .AddScoped(TriggerStore)
 262385            .AddScoped(WorkflowExecutionLogStore)
 262386            .AddScoped(ActivityExecutionLogStore)
 262387
 262388            // Lazy services.
 198389            .AddScoped<Func<IEnumerable<IWorkflowsProvider>>>(sp => sp.GetServices<IWorkflowsProvider>)
 724390            .AddScoped<Func<IEnumerable<IWorkflowMaterializer>>>(sp => sp.GetServices<IWorkflowMaterializer>)
 262391
 262392            // Noop stores.
 262393            .AddScoped<MemoryWorkflowExecutionLogStore>()
 262394            .AddScoped<MemoryActivityExecutionStore>()
 262395
 262396            // Memory stores.
 262397            .AddMemoryStore<StoredBookmark, MemoryBookmarkStore>()
 262398            .AddMemoryStore<StoredTrigger, MemoryTriggerStore>()
 262399            .AddMemoryStore<BookmarkQueueItem, MemoryBookmarkQueueStore>()
 262400            .AddMemoryStore<BookmarkQueueDeadLetterItem, MemoryBookmarkQueueDeadLetterStore>()
 262401            .AddMemoryStore<WorkflowExecutionLogRecord, MemoryWorkflowExecutionLogStore>()
 262402            .AddMemoryStore<ActivityExecutionRecord, MemoryActivityExecutionStore>()
 262403
 262404            // Startup tasks, background tasks, and recurring tasks.
 262405            .AddStartupTask<PopulateRegistriesStartupTask>()
 262406            .AddRecurringTask<TriggerBookmarkQueueRecurringTask>(TimeSpan.FromMinutes(1))
 262407            .AddRecurringTask<PurgeBookmarkQueueRecurringTask>(TimeSpan.FromSeconds(10))
 262408            .AddRecurringTask<RestartInterruptedWorkflowsTask>(TimeSpan.FromMinutes(5)) // Same default as the workflow 
 262409            .AddRecurringTask<ProcessWorkflowDispatchOutboxRecurringTask>(TimeSpan.FromSeconds(10))
 262410
 262411            // Distributed locking.
 262412            .AddSingleton(DistributedLockProvider)
 262413
 262414            // Workflow providers.
 262415            .AddWorkflowsProvider<ClrWorkflowsProvider>()
 262416
 262417            // UI property handlers.
 262418            .AddScoped<IPropertyUIHandler, DispatcherChannelOptionsProvider>()
 262419
 262420            // Domain handlers.
 262421            .AddCommandHandler<DispatchWorkflowCommandHandler>()
 262422            .AddCommandHandler<DispatchStimulusCommandHandler>()
 262423            .AddCommandHandler<CancelWorkflowsCommandHandler>()
 262424            .AddNotificationHandler<ResumeDispatchWorkflowActivity>()
 262425            .AddNotificationHandler<ResumeBulkDispatchWorkflowActivity>()
 262426            .AddNotificationHandler<ProcessWorkflowDispatchOutbox>()
 262427            .AddNotificationHandler<ResumeExecuteWorkflowActivity>()
 262428            .AddNotificationHandler<IndexTriggers>()
 262429            .AddNotificationHandler<CancelBackgroundActivities>()
 262430            .AddNotificationHandler<DeleteBookmarks>()
 262431            .AddNotificationHandler<DeleteTriggers>()
 262432            .AddNotificationHandler<DeleteActivityExecutionLogRecords>()
 262433            .AddNotificationHandler<DeleteWorkflowExecutionLogRecords>()
 262434            .AddNotificationHandler<RefreshActivityRegistry>()
 262435            .AddNotificationHandler<SignalBookmarkQueueWorker>()
 262436            .AddNotificationHandler<EvaluateParentLogPersistenceModes>()
 262437            .AddNotificationHandler<CaptureActivityExecutionState>()
 262438            .AddNotificationHandler<ValidateWorkflowRequestHandler>()
 262439
 262440            // Workflow activation strategies.
 262441            .AddScoped<IWorkflowActivationStrategy, SingletonStrategy>()
 262442            .AddScoped<IWorkflowActivationStrategy, CorrelatedSingletonStrategy>()
 262443            .AddScoped<IWorkflowActivationStrategy, CorrelationStrategy>()
 262444            ;
 445
 262446        Services.TryAddScoped<IWorkflowDispatchOutbox>(sp => ActivatorUtilities.CreateInstance<WorkflowDispatchOutbox>(s
 262447        Services.TryAddScoped(WorkflowDispatchOutboxStore);
 262448        Services.TryAddScoped<IWorkflowDispatchOutboxProcessor, WorkflowDispatchOutboxProcessor>();
 262449    }
 450
 451    private void RegisterWorkflowTypeAliases(SerializationTypeOptions options)
 452    {
 238453        WorkflowRuntimeTypeAliasRegistrar.Register(options, GetRegisteredWorkflowTypes());
 238454    }
 455
 456    private IEnumerable<Type> GetRegisteredWorkflowTypes()
 457    {
 238458        return WorkflowTypes
 661459            .Concat(Workflows.Keys.Select(TryResolveWorkflowType).Where(type => type != null).Select(type => type!))
 238460            .Distinct();
 461    }
 462
 463    private static Type? TryResolveWorkflowType(string typeName)
 464    {
 465        Type? type;
 466
 467        try
 468        {
 441469            type = Type.GetType(typeName, false);
 441470        }
 0471        catch (Exception e) when (e is ArgumentException or FileLoadException or FileNotFoundException or TypeLoadExcept
 472        {
 0473            return null;
 474        }
 475
 441476        return type != null && typeof(IWorkflow).IsAssignableFrom(type) && type is { IsAbstract: false, IsInterface: fal
 441477            ? type
 441478            : null;
 0479    }
 480}