diff --git a/Directory.Packages.props b/Directory.Packages.props index ea39e0d4..0ae482e5 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -141,13 +141,13 @@ - - - - - - - + + + + + + + @@ -243,4 +243,4 @@ - \ No newline at end of file + diff --git a/src/modules/scheduling/Elsa.Scheduling.Quartz.EFCore.MySql/ShellFeatures/QuartzMySqlFeature.cs b/src/modules/scheduling/Elsa.Scheduling.Quartz.EFCore.MySql/ShellFeatures/QuartzMySqlFeature.cs index 2af0f17b..ecb4c03a 100644 --- a/src/modules/scheduling/Elsa.Scheduling.Quartz.EFCore.MySql/ShellFeatures/QuartzMySqlFeature.cs +++ b/src/modules/scheduling/Elsa.Scheduling.Quartz.EFCore.MySql/ShellFeatures/QuartzMySqlFeature.cs @@ -35,8 +35,7 @@ public void ConfigureServices(IServiceCollection services) else services.AddDbContextFactory(Configure); - services.AddTransient(sp => - new EfCoreMigrationHandler(sp.GetRequiredService>())); + services.AddShellInitializer(LifecyclePhase.Prepare, order: 100); services.AddQuartz(quartz => { diff --git a/src/modules/scheduling/Elsa.Scheduling.Quartz.EFCore.PostgreSql/ShellFeatures/QuartzPostgreSqlFeature.cs b/src/modules/scheduling/Elsa.Scheduling.Quartz.EFCore.PostgreSql/ShellFeatures/QuartzPostgreSqlFeature.cs index c2b9ba79..52e2eb0d 100644 --- a/src/modules/scheduling/Elsa.Scheduling.Quartz.EFCore.PostgreSql/ShellFeatures/QuartzPostgreSqlFeature.cs +++ b/src/modules/scheduling/Elsa.Scheduling.Quartz.EFCore.PostgreSql/ShellFeatures/QuartzPostgreSqlFeature.cs @@ -35,8 +35,7 @@ public void ConfigureServices(IServiceCollection services) else services.AddDbContextFactory(Configure); - services.AddTransient(sp => - new EfCoreMigrationHandler(sp.GetRequiredService>())); + services.AddShellInitializer(LifecyclePhase.Prepare, order: 100); services.AddQuartz(quartz => { diff --git a/src/modules/scheduling/Elsa.Scheduling.Quartz.EFCore.SqlServer/ShellFeatures/QuartzSqlServerFeature.cs b/src/modules/scheduling/Elsa.Scheduling.Quartz.EFCore.SqlServer/ShellFeatures/QuartzSqlServerFeature.cs index 538385a6..87943402 100644 --- a/src/modules/scheduling/Elsa.Scheduling.Quartz.EFCore.SqlServer/ShellFeatures/QuartzSqlServerFeature.cs +++ b/src/modules/scheduling/Elsa.Scheduling.Quartz.EFCore.SqlServer/ShellFeatures/QuartzSqlServerFeature.cs @@ -35,8 +35,7 @@ public void ConfigureServices(IServiceCollection services) else services.AddDbContextFactory(Configure); - services.AddTransient(sp => - new EfCoreMigrationHandler(sp.GetRequiredService>())); + services.AddShellInitializer(LifecyclePhase.Prepare, order: 100); // AddQuartz is additive — layers the persistent store onto the base // AddQuartz call already made by QuartzFeature (which ran first via DependsOn). diff --git a/src/modules/scheduling/Elsa.Scheduling.Quartz.EFCore.Sqlite/ShellFeatures/QuartzSqliteFeature.cs b/src/modules/scheduling/Elsa.Scheduling.Quartz.EFCore.Sqlite/ShellFeatures/QuartzSqliteFeature.cs index ce3263cd..e16ab026 100644 --- a/src/modules/scheduling/Elsa.Scheduling.Quartz.EFCore.Sqlite/ShellFeatures/QuartzSqliteFeature.cs +++ b/src/modules/scheduling/Elsa.Scheduling.Quartz.EFCore.Sqlite/ShellFeatures/QuartzSqliteFeature.cs @@ -38,9 +38,7 @@ public void ConfigureServices(IServiceCollection services) else services.AddDbContextFactory(Configure); - services.AddTransient(sp => - new EfCoreMigrationHandler( - sp.GetRequiredService>())); + services.AddShellInitializer(LifecyclePhase.Prepare, order: 100); } public void PostConfigureServices(IServiceCollection services) diff --git a/src/modules/scheduling/Elsa.Scheduling.Quartz/ShellFeatures/QuartzShellLifecycleHandler.cs b/src/modules/scheduling/Elsa.Scheduling.Quartz/ShellFeatures/QuartzShellLifecycleHandler.cs index 843e409b..66fb2e4a 100644 --- a/src/modules/scheduling/Elsa.Scheduling.Quartz/ShellFeatures/QuartzShellLifecycleHandler.cs +++ b/src/modules/scheduling/Elsa.Scheduling.Quartz/ShellFeatures/QuartzShellLifecycleHandler.cs @@ -15,6 +15,7 @@ namespace Elsa.Scheduling.Quartz.ShellFeatures; /// so the AwaitApplicationStarted deferral logic from QuartzHostedService /// is intentionally omitted — it is irrelevant in this context. /// +[LifecycleOrder(LifecyclePhase.Start, 100)] public class QuartzShellLifecycleHandler( IQuartzSchedulerFactory schedulerFactory, IHostApplicationLifetime appLifetime, diff --git a/test/modules/scheduling/Elsa.Scheduling.Quartz.UnitTests/Elsa.Scheduling.Quartz.UnitTests.csproj b/test/modules/scheduling/Elsa.Scheduling.Quartz.UnitTests/Elsa.Scheduling.Quartz.UnitTests.csproj index c9bdbb85..c3e2a940 100644 --- a/test/modules/scheduling/Elsa.Scheduling.Quartz.UnitTests/Elsa.Scheduling.Quartz.UnitTests.csproj +++ b/test/modules/scheduling/Elsa.Scheduling.Quartz.UnitTests/Elsa.Scheduling.Quartz.UnitTests.csproj @@ -2,6 +2,10 @@ + + + + diff --git a/test/modules/scheduling/Elsa.Scheduling.Quartz.UnitTests/ShellFeatures/QuartzFeatureTests.cs b/test/modules/scheduling/Elsa.Scheduling.Quartz.UnitTests/ShellFeatures/QuartzFeatureTests.cs index 5210ef2d..51399a8e 100644 --- a/test/modules/scheduling/Elsa.Scheduling.Quartz.UnitTests/ShellFeatures/QuartzFeatureTests.cs +++ b/test/modules/scheduling/Elsa.Scheduling.Quartz.UnitTests/ShellFeatures/QuartzFeatureTests.cs @@ -1,7 +1,12 @@ using CShells.Features; using CShells.Lifecycle; +using Elsa.Scheduling.Quartz.EFCore.MySql.ShellFeatures; +using Elsa.Scheduling.Quartz.EFCore.PostgreSql.ShellFeatures; +using Elsa.Scheduling.Quartz.EFCore.SqlServer.ShellFeatures; +using Elsa.Scheduling.Quartz.EFCore.Sqlite.ShellFeatures; using Elsa.Scheduling.Quartz.ShellFeatures; using Microsoft.Extensions.DependencyInjection; +using System.Reflection; namespace Elsa.Scheduling.Quartz.UnitTests.ShellFeatures; @@ -26,6 +31,42 @@ public void SchedulerInitializer_IsRegisteredDuringPostConfigure() Assert.NotNull(initializerRegistrations[1].ImplementationFactory); } + [Fact] + public void SchedulerInitializer_RunsInStartPhase() + { + var order = typeof(QuartzShellLifecycleHandler).GetCustomAttribute(); + + Assert.NotNull(order); + Assert.Equal(LifecyclePhase.Start, order.Phase); + Assert.Equal(100, order.Order); + } + + [Theory] + [MemberData(nameof(QuartzStoreFeatures))] + public void StoreMigrationInitializer_RunsInPreparePhase(IShellFeature feature) + { + var services = new ServiceCollection(); + + feature.ConfigureServices(services); + + var initializer = Assert.Single(services, x => x.ServiceType == typeof(IShellInitializer)); + var registrationDescriptor = Assert.Single(services, x => x.ServiceType == typeof(ShellInitializerRegistration)); + var registration = Assert.IsType(registrationDescriptor.ImplementationInstance); + + Assert.NotNull(initializer.ImplementationFactory); + Assert.Equal(LifecyclePhase.Prepare, registration.Phase); + Assert.Equal(100, registration.Order); + Assert.True(typeof(IShellInitializer).IsAssignableFrom(registration.InitializerType)); + } + + public static TheoryData QuartzStoreFeatures() => new() + { + new QuartzMySqlFeature(), + new QuartzPostgreSqlFeature(), + new QuartzSqlServerFeature(), + new QuartzSqliteFeature() + }; + private sealed class DependentInitializer : IShellInitializer { public Task InitializeAsync(CancellationToken cancellationToken = default) => Task.CompletedTask;