using LiteCharms.Features.Quartz; using LiteCharms.Features.Quartz.Abstractions; namespace LiteCharms.Features.Extensions; public static class Quartz { private const string databaseConfigName = "PostgresScheduler"; public static IServiceCollection AddQuartzSchedulerClient(this IServiceCollection services, string schedulerName, IConfiguration configuration) { var connectionString = configuration.GetConnectionString(databaseConfigName); services.ConfigureCommon(); services.AddQuartz(config => { config.SchedulerName = schedulerName; config.SchedulerId = "AUTO"; config.UseSimpleTypeLoader(); config.UseDefaultThreadPool(options => options.MaxConcurrency = 0); config.UseTimeZoneConverter(); config.UsePersistentStore(storage => { storage.PerformSchemaValidation = false; storage.UseSystemTextJsonSerializer(); storage.SetProperty("quartz.jobStore.clustered", "true"); storage.SetProperty("quartz.jobStore.tablePrefix", "qrtz_"); storage.UsePostgres(connectionString!); storage.UseClustering(cluster => { cluster.CheckinInterval = TimeSpan.FromSeconds(30); cluster.CheckinMisfireThreshold = TimeSpan.FromSeconds(90); }); }); }); return services; } public static IServiceCollection AddQuartzScheduler(this IServiceCollection services, string schedulerName, IConfiguration configuration) { var connectionString = configuration.GetConnectionString(databaseConfigName); services.ConfigureCommon(); services.AddQuartzHostedService(options => options.WaitForJobsToComplete = true); services.AddQuartz(config => { config.SchedulerName = schedulerName; config.SchedulerId = "AUTO"; config.InterruptJobsOnShutdown = true; config.InterruptJobsOnShutdownWithWait = true; config.MaxBatchSize = 5; config.UseSimpleTypeLoader(); config.UseDefaultThreadPool(options => options.MaxConcurrency = 1); config.UseTimeZoneConverter(); config.SetProperty("quartz.jobStore.misfireThreshold", TimeSpan.FromMinutes(2).TotalMilliseconds.ToString()); config.UsePersistentStore(storage => { storage.PerformSchemaValidation = false; storage.UseSystemTextJsonSerializer(); storage.SetProperty("quartz.jobStore.clustered", "true"); storage.SetProperty("quartz.jobStore.tablePrefix", "qrtz_"); storage.UsePostgres(connectionString!); storage.UseClustering(cluster => { cluster.CheckinInterval = TimeSpan.FromSeconds(30); cluster.CheckinMisfireThreshold = TimeSpan.FromSeconds(90); }); }); }); return services; } private static IServiceCollection ConfigureCommon(this IServiceCollection services) { services.Configure(options => { options.Scheduling.IgnoreDuplicates = true; options.Scheduling.OverWriteExistingData = true; options["quartz.plugin.jobHistory.type"] = "Quartz.Plugin.History.LoggingJobHistoryPlugin, Quartz.Plugins"; options["quartz.plugin.triggerHistory.type"] = "Quartz.Plugin.History.LoggingTriggerHistoryPlugin, Quartz.Plugins"; }); services.AddTransient(); services.AddTransient(); return services; } }