< 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: 235
Uncovered lines: 13
Coverable lines: 248
Total lines: 476
Line coverage: 94.7%
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))]
 23843public class WorkflowRuntimeFeature(IModule module) : FeatureBase(module)
 44{
 40645    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>
 84050    public IDictionary<string, Func<IServiceProvider, ValueTask<IWorkflow>>> Workflows { get; set; } = new Dictionary<st
 65451    private ISet<Type> WorkflowTypes { get; } = new HashSet<Type>();
 52
 53    /// <summary>
 54    /// A factory that instantiates a concrete <see cref="IWorkflowRuntime"/>.
 55    /// </summary>
 61656    public Func<IServiceProvider, IWorkflowRuntime> WorkflowRuntime { get; set; } = sp => ActivatorUtilities.CreateInsta
 57
 58    /// <summary>
 59    /// A factory that instantiates an <see cref="IWorkflowDispatcher"/>.
 60    /// </summary>
 45861    public Func<IServiceProvider, IWorkflowDispatcher> WorkflowDispatcher { get; set; } = sp =>
 23862    {
 47263        var decoratedService = ActivatorUtilities.CreateInstance<BackgroundWorkflowDispatcher>(sp);
 47264        var transactionalService = ActivatorUtilities.CreateInstance<TransactionalWorkflowDispatcher>(sp, decoratedServi
 47265        return ActivatorUtilities.CreateInstance<ValidatingWorkflowDispatcher>(sp, transactionalService);
 23866    };
 67
 68    /// <summary>
 69    /// A factory that instantiates an <see cref="IStimulusDispatcher"/>.
 70    /// </summary>
 46971    public Func<IServiceProvider, IStimulusDispatcher> StimulusDispatcher { get; set; } = sp => ActivatorUtilities.Creat
 72
 73    /// <summary>
 74    /// A factory that instantiates an <see cref="IWorkflowCancellationDispatcher"/>.
 75    /// </summary>
 46176    public Func<IServiceProvider, IWorkflowCancellationDispatcher> WorkflowCancellationDispatcher { get; set; } = sp => 
 77
 78    /// <summary>
 79    /// A factory that instantiates an <see cref="IWorkflowDispatchOutboxStore"/>.
 80    /// </summary>
 45881    public Func<IServiceProvider, IWorkflowDispatchOutboxStore> WorkflowDispatchOutboxStore { get; set; } = sp => Activa
 82
 83    /// <summary>
 84    /// A factory that instantiates an <see cref="IBookmarkStore"/>.
 85    /// </summary>
 81186    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>
 81191    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>
 63296    public Func<IServiceProvider, IBookmarkQueueDeadLetterStore> BookmarkQueueDeadLetterStore { get; set; } = sp => sp.G
 97
 98    /// <summary>
 99    /// A factory that instantiates an <see cref="ITriggerStore"/>.
 100    /// </summary>
 709101    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>
 711106    public Func<IServiceProvider, IWorkflowExecutionLogStore> WorkflowExecutionLogStore { get; set; } = sp => sp.GetRequ
 107
 108    /// <summary>
 109    /// A factory that instantiates an <see cref="IActivityExecutionStore"/>.
 110    /// </summary>
 698111    public Func<IServiceProvider, IActivityExecutionStore> ActivityExecutionLogStore { get; set; } = sp => sp.GetRequire
 112
 113    /// <summary>
 114    /// A factory that instantiates an <see cref="IDistributedLockProvider"/>.
 115    /// </summary>
 633116    public Func<IServiceProvider, IDistributedLockProvider> DistributedLockProvider { get; set; } = _ => new FileDistrib
 117
 118    /// <summary>
 119    /// A factory that instantiates an <see cref="ITaskDispatcher"/>.
 120    /// </summary>
 458121    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>
 633126    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>
 971131    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>
 971136    public Func<IServiceProvider, ILogRecordSink<WorkflowExecutionLogRecord>> WorkflowExecutionLogSink { get; set; } = s
 137
 138    /// <summary>
 139    /// A factory that instantiates an <see cref="ICommandHandler"/>.
 140    /// </summary>
 238141    public Func<IServiceProvider, ICommandHandler> DispatchWorkflowCommandHandler { get; set; } = sp => sp.GetRequiredSe
 142
 143    /// <summary>
 144    /// A factory that instantiates an <see cref="IWorkflowResumer"/>.
 145    /// </summary>
 872146    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>
 751151    public Func<IServiceProvider, IBookmarkQueueWorker> BookmarkQueueWorker { get; set; } = sp => sp.GetRequiredService<
 152
 153    /// <summary>
 154    /// A delegate to configure the <see cref="DistributedLockingOptions"/>.
 155    /// </summary>
 636156    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")]
 458162    public Action<WorkflowInboxCleanupOptions> WorkflowInboxCleanupOptions { get; set; } = _ => { };
 163
 164    /// <summary>
 165    /// A delegate to configure the <see cref="WorkflowDispatcherOptions"/>.
 166    /// </summary>
 626167    public Action<WorkflowDispatcherOptions> WorkflowDispatcherOptions { get; set; } = _ => { };
 168
 169    /// <summary>
 170    /// A delegate to configure the <see cref="BookmarkQueuePurgeOptions"/>.
 171    /// </summary>
 463172    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    {
 22197        AddWorkflow(typeof(T));
 22198        return this;
 199    }
 200
 201    /// <summary>
 202    /// Register the specified workflow type.
 203    /// </summary>
 204    public WorkflowRuntimeFeature AddWorkflow(Type workflowType)
 205    {
 220206        Workflows.Add(workflowType);
 216207        WorkflowTypes.Add(workflowType);
 216208        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    {
 220246        Module.AddActivitiesFrom<WorkflowRuntimeFeature>();
 220247        Module.Configure<WorkflowsFeature>(workflows =>
 220248        {
 220249            // ExecutionCycleAwareCommitStateHandler decorates DefaultCommitStateHandler â€” disposes the execution cycle 
 220250            // commit so the drain orchestrator's await-disposed sequencing can land its Interrupted write last.
 733251            workflows.CommitStateHandler = sp => sp.GetRequiredService<Elsa.Workflows.Runtime.Services.ExecutionCycleAwa
 440252        });
 253
 220254        Services.Configure<RecurringTaskOptions>(options =>
 220255        {
 70256            options.Schedule.ConfigureTask<TriggerBookmarkQueueRecurringTask>(TimeSpan.FromSeconds(10));
 290257        });
 220258    }
 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>
 225265    public Action<GracefulShutdownOptions>? GracefulShutdown { get; set; }
 266
 267    public override void Apply()
 268    {
 269        // Options.
 220270        Services.Configure(DistributedLockingOptions);
 220271        Services.Configure(WorkflowInboxCleanupOptions);
 220272        Services.Configure(WorkflowDispatcherOptions);
 220273        Services.Configure(BookmarkQueuePurgeOptions);
 220274        Services.Configure<SerializationTypeOptions>(RegisterWorkflowTypeAliases);
 558275        Services.Configure<RuntimeOptions>(options => { options.Workflows = Workflows; });
 220276        Services.Configure<WorkflowDispatcherOptions>(options =>
 220277        {
 168278            options.Channels.AddRange(WorkflowDispatcherChannels.Values);
 388279        });
 220280        Services.AddGracefulShutdownOptions(GracefulShutdown);
 281
 282        // Graceful-shutdown core (US1 â€” quiescence machinery).
 220283        Services
 80284            .AddSingleton<IQuiescenceSignal>(sp => new Elsa.Workflows.Runtime.Services.QuiescenceSignal(
 80285                sp.GetRequiredService<IOptions<GracefulShutdownOptions>>(),
 80286                sp.GetRequiredService<ISystemClock>(),
 80287                sp.GetRequiredService<IExecutionCycleRegistry>(),
 80288                sp.GetRequiredService<IServiceScopeFactory>()))
 220289            .AddSingleton<IIngressSourceRegistry, Elsa.Workflows.Runtime.Services.IngressSourceRegistry>()
 220290            .AddSingleton<IExecutionCycleRegistry, Elsa.Workflows.Runtime.Services.ExecutionCycleRegistry>()
 220291            // Lazy collection breaks the otherwise-circular DI chain QuiescenceSignal â†’ IExecutionCycleRegistry â†’
 220292            // IIngressSourceRegistry â†’ IEnumerable<IIngressSource> â†’ IQuiescenceSignal. Adapters take a direct
 220293            // IQuiescenceSignal dependency; the registry materializes the collection on first read.
 158294            .AddSingleton(sp => new Lazy<IEnumerable<IIngressSource>>(sp.GetServices<IIngressSource>))
 220295            // Drain orchestrator + hosted service (US1). See FR-029 / R5 â€” heartbeat must outlive drain.
 220296            .AddSingleton<IDrainOrchestrator, Elsa.Workflows.Runtime.Services.DrainOrchestrator>()
 220297            .AddHostedService<Elsa.Workflows.Runtime.HostedServices.DrainOrchestratorHostedService>()
 220298            // Domain service that backs all runtime-admin transports (US2). Encapsulates the audit-on-effective-
 220299            // transition rule (SC-007) so transports stay thin. Scoped because INotificationSender is scoped.
 220300            .AddScoped<IWorkflowRuntimeAdminService, Elsa.Workflows.Runtime.Services.WorkflowRuntimeAdminService>()
 220301            // Interrupted-workflow recovery on shell activation (US3). Disjoint from the timeout-based
 220302            // RestartInterruptedWorkflowsTask: filter is SubStatus = Interrupted; that task's filter is IsExecuting=tru
 220303            .AddScoped<IInterruptedRecoveryScanner, Elsa.Workflows.Runtime.Services.InterruptedRecoveryScanner>()
 220304            .AddStartupTask<Elsa.Workflows.Runtime.StartupTasks.RecoverInterruptedWorkflowsStartupTask>()
 220305            // Internal bookmark-queue processor surfaced as an ingress source for diagnostic visibility (FR-006).
 220306            // Pause behavior is enforced inside BookmarkQueueProcessor via IQuiescenceSignal (FR-024).
 220307            .AddSingleton<IIngressSource, Elsa.Workflows.Runtime.IngressSources.InternalBookmarkQueueIngressSource>()
 220308            // Re-applies persisted pause state on activation when PausePersistence = AcrossReactivations (FR-028).
 220309            .AddStartupTask<Elsa.Workflows.Runtime.StartupTasks.InitializePauseStateStartupTask>();
 310
 220311        Services
 220312            // Core.
 220313            .AddScoped<ITriggerIndexer, TriggerIndexer>()
 220314            .AddScoped<IWorkflowInstanceFactory, WorkflowInstanceFactory>()
 220315            .AddScoped<IWorkflowHostFactory, WorkflowHostFactory>()
 220316            .AddScoped<IBackgroundActivityInvoker, BackgroundActivityInvoker>()
 220317            .AddScoped(WorkflowRuntime)
 220318            .AddScoped(WorkflowDispatcher)
 220319            .AddScoped(StimulusDispatcher)
 220320            .AddScoped(WorkflowCancellationDispatcher)
 220321            .AddScoped(RunTaskDispatcher)
 220322            .AddScoped(ActivityExecutionLogSink)
 220323            .AddScoped(WorkflowExecutionLogSink)
 220324            .AddSingleton(BackgroundActivityScheduler)
 220325            .AddSingleton<RandomLongIdentityGenerator>()
 220326            .AddSingleton<IBookmarkQueueSignaler, BookmarkQueueSignaler>()
 220327            .AddScoped(BookmarkQueueWorker)
 220328            .AddScoped<IBookmarkManager, DefaultBookmarkManager>()
 220329            .AddScoped<IActivityExecutionManager, DefaultActivityExecutionManager>()
 220330            .AddScoped<IActivityExecutionStatsService, ActivityExecutionStatsService>()
 220331            .AddScoped<IActivityExecutionMapper, DefaultActivityExecutionMapper>()
 220332            .AddScoped<IWorkflowDefinitionStorePopulator, DefaultWorkflowDefinitionStorePopulator>()
 220333            .AddScoped<IRegistriesPopulator, DefaultRegistriesPopulator>()
 220334            .AddScoped<IWorkflowDefinitionsRefresher, WorkflowDefinitionsRefresher>()
 220335            .AddScoped<IWorkflowDefinitionsReloader, WorkflowDefinitionsReloader>()
 220336            .AddScoped<IWorkflowRegistry, DefaultWorkflowRegistry>()
 220337            .AddScoped<IWorkflowMatcher, WorkflowMatcher>()
 220338            .AddScoped<IWorkflowInvoker, WorkflowInvoker>()
 220339            .AddScoped<IStimulusSender, StimulusSender>()
 220340            .AddScoped<ITriggerBoundWorkflowService, TriggerBoundWorkflowService>()
 220341            .AddScoped<IBookmarkBoundWorkflowService, BookmarkBoundWorkflowService>()
 220342            .AddScoped<ITaskReporter, TaskReporter>()
 220343            .AddScoped<SynchronousTaskDispatcher>()
 220344            .AddScoped<BackgroundTaskDispatcher>()
 220345            .AddScoped<StoreActivityExecutionLogSink>()
 220346            .AddScoped<StoreWorkflowExecutionLogSink>()
 220347            .AddScoped<DispatchWorkflowCommandHandler>()
 220348            .AddScoped<IEventPublisher, EventPublisher>()
 220349            .AddScoped<IBookmarkUpdater, BookmarkUpdater>()
 220350            .AddScoped<IBookmarksPersister, BookmarksPersister>()
 220351            .AddScoped<IBookmarkResumer, BookmarkResumer>()
 220352            .AddScoped<IBookmarkQueue, StoreBookmarkQueue>()
 220353            .AddScoped<IBookmarkQueueDeadLetterManager, BookmarkQueueDeadLetterManager>()
 220354            .AddScoped(WorkflowResumer)
 220355            .AddScoped<WorkflowResumer>()
 220356            .AddScoped(BookmarkQueueWorker)
 220357            .AddScoped<BookmarkQueueWorker>()
 220358            .AddScoped<ITriggerInvoker, TriggerInvoker>()
 220359            .AddScoped<IWorkflowCanceler, WorkflowCanceler>()
 220360            .AddScoped<IWorkflowCancellationService, WorkflowCancellationService>()
 220361            .AddScoped<IWorkflowActivationStrategyEvaluator, DefaultWorkflowActivationStrategyEvaluator>()
 220362            .AddScoped<IWorkflowStarter, DefaultWorkflowStarter>()
 220363            .AddScoped<IWorkflowRestarter, DefaultWorkflowRestarter>()
 220364            .AddScoped<IBookmarkQueuePurger, DefaultBookmarkQueuePurger>()
 220365            .AddSingleton<IWorkflowDispatchOutboxAccessor, WorkflowDispatchOutboxAccessor>()
 220366            .AddScoped<ILogRecordExtractor<WorkflowExecutionLogRecord>, WorkflowExecutionLogRecordExtractor>()
 220367            .AddScoped<IActivityPropertyLogPersistenceEvaluator, ActivityPropertyLogPersistenceEvaluator>()
 220368            .AddScoped<IBookmarkQueueProcessor, BookmarkQueueProcessor>()
 220369            .AddScoped<DefaultCommitStateHandler>()
 220370            .AddScoped<Elsa.Workflows.Runtime.Services.ExecutionCycleAwareCommitStateHandler>()
 220371            .AddScoped<WorkflowHeartbeatGeneratorFactory>()
 220372
 220373            // Deprecated services.
 220374            .AddScoped<IWorkflowInbox, StimulusProxyWorkflowInbox>()
 220375
 220376            // Stores.
 220377            .AddScoped(BookmarkStore)
 220378            .AddScoped(BookmarkQueueStore)
 220379            .AddScoped(BookmarkQueueDeadLetterStore)
 220380            .AddScoped(TriggerStore)
 220381            .AddScoped(WorkflowExecutionLogStore)
 220382            .AddScoped(ActivityExecutionLogStore)
 220383
 220384            // Lazy services.
 174385            .AddScoped<Func<IEnumerable<IWorkflowsProvider>>>(sp => sp.GetServices<IWorkflowsProvider>)
 669386            .AddScoped<Func<IEnumerable<IWorkflowMaterializer>>>(sp => sp.GetServices<IWorkflowMaterializer>)
 220387
 220388            // Noop stores.
 220389            .AddScoped<MemoryWorkflowExecutionLogStore>()
 220390            .AddScoped<MemoryActivityExecutionStore>()
 220391
 220392            // Memory stores.
 220393            .AddMemoryStore<StoredBookmark, MemoryBookmarkStore>()
 220394            .AddMemoryStore<StoredTrigger, MemoryTriggerStore>()
 220395            .AddMemoryStore<BookmarkQueueItem, MemoryBookmarkQueueStore>()
 220396            .AddMemoryStore<BookmarkQueueDeadLetterItem, MemoryBookmarkQueueDeadLetterStore>()
 220397            .AddMemoryStore<WorkflowExecutionLogRecord, MemoryWorkflowExecutionLogStore>()
 220398            .AddMemoryStore<ActivityExecutionRecord, MemoryActivityExecutionStore>()
 220399
 220400            // Startup tasks, background tasks, and recurring tasks.
 220401            .AddStartupTask<PopulateRegistriesStartupTask>()
 220402            .AddRecurringTask<TriggerBookmarkQueueRecurringTask>(TimeSpan.FromMinutes(1))
 220403            .AddRecurringTask<PurgeBookmarkQueueRecurringTask>(TimeSpan.FromSeconds(10))
 220404            .AddRecurringTask<RestartInterruptedWorkflowsTask>(TimeSpan.FromMinutes(5)) // Same default as the workflow 
 220405            .AddRecurringTask<ProcessWorkflowDispatchOutboxRecurringTask>(TimeSpan.FromSeconds(10))
 220406
 220407            // Distributed locking.
 220408            .AddSingleton(DistributedLockProvider)
 220409
 220410            // Workflow providers.
 220411            .AddWorkflowsProvider<ClrWorkflowsProvider>()
 220412
 220413            // UI property handlers.
 220414            .AddScoped<IPropertyUIHandler, DispatcherChannelOptionsProvider>()
 220415
 220416            // Domain handlers.
 220417            .AddCommandHandler<DispatchWorkflowCommandHandler>()
 220418            .AddCommandHandler<DispatchStimulusCommandHandler>()
 220419            .AddCommandHandler<CancelWorkflowsCommandHandler>()
 220420            .AddNotificationHandler<ResumeDispatchWorkflowActivity>()
 220421            .AddNotificationHandler<ResumeBulkDispatchWorkflowActivity>()
 220422            .AddNotificationHandler<ProcessWorkflowDispatchOutbox>()
 220423            .AddNotificationHandler<ResumeExecuteWorkflowActivity>()
 220424            .AddNotificationHandler<IndexTriggers>()
 220425            .AddNotificationHandler<CancelBackgroundActivities>()
 220426            .AddNotificationHandler<DeleteBookmarks>()
 220427            .AddNotificationHandler<DeleteTriggers>()
 220428            .AddNotificationHandler<DeleteActivityExecutionLogRecords>()
 220429            .AddNotificationHandler<DeleteWorkflowExecutionLogRecords>()
 220430            .AddNotificationHandler<RefreshActivityRegistry>()
 220431            .AddNotificationHandler<SignalBookmarkQueueWorker>()
 220432            .AddNotificationHandler<EvaluateParentLogPersistenceModes>()
 220433            .AddNotificationHandler<CaptureActivityExecutionState>()
 220434            .AddNotificationHandler<ValidateWorkflowRequestHandler>()
 220435
 220436            // Workflow activation strategies.
 220437            .AddScoped<IWorkflowActivationStrategy, SingletonStrategy>()
 220438            .AddScoped<IWorkflowActivationStrategy, CorrelatedSingletonStrategy>()
 220439            .AddScoped<IWorkflowActivationStrategy, CorrelationStrategy>()
 220440            ;
 441
 220442        Services.TryAddScoped<IWorkflowDispatchOutbox>(sp => ActivatorUtilities.CreateInstance<WorkflowDispatchOutbox>(s
 220443        Services.TryAddScoped(WorkflowDispatchOutboxStore);
 220444        Services.TryAddScoped<IWorkflowDispatchOutboxProcessor, WorkflowDispatchOutboxProcessor>();
 220445    }
 446
 447    private void RegisterWorkflowTypeAliases(SerializationTypeOptions options)
 448    {
 200449        WorkflowRuntimeTypeAliasRegistrar.Register(options, GetRegisteredWorkflowTypes());
 200450    }
 451
 452    private IEnumerable<Type> GetRegisteredWorkflowTypes()
 453    {
 200454        return WorkflowTypes
 643455            .Concat(Workflows.Keys.Select(TryResolveWorkflowType).Where(type => type != null).Select(type => type!))
 200456            .Distinct();
 457    }
 458
 459    private static Type? TryResolveWorkflowType(string typeName)
 460    {
 461        Type? type;
 462
 463        try
 464        {
 429465            type = Type.GetType(typeName, false);
 429466        }
 0467        catch (Exception e) when (e is ArgumentException or FileLoadException or FileNotFoundException or TypeLoadExcept
 468        {
 0469            return null;
 470        }
 471
 429472        return type != null && typeof(IWorkflow).IsAssignableFrom(type) && type is { IsAbstract: false, IsInterface: fal
 429473            ? type
 429474            : null;
 0475    }
 476}