public void AddServices(IServiceCollection services)
        {
            //Options and extension service
            var options = new QuartzOptions();

            _action.Invoke(options);
            services.AddSingleton(options);
            //List<IQuartzOptionsExtension> quartzOptionsExtensions = options.Extensions.Where(p => p is MySqlQuartzOptionsExtension || p is SqlServerQuartzOptionsExtension || p is InMemoryStorageOptionsExtension).ToList();

            //if (quartzOptionsExtensions.Count > 1)
            //{
            //    throw new ArgumentException("目前只允许配置一种持久化类型");
            //}

            foreach (IQuartzOptionsExtension serviceExtension in options.Extensions)
            {
                serviceExtension.AddServices(services);
            }

            //初始化定时任务查找器
            services.TryAddSingleton <IJobTypeFinder, JobTypeFinder>();
            //注入所有IJob
            services.InitializeJobs();

            services.AddTransient <ISchedulerFactory, StdSchedulerFactory>();
            services.AddSingleton <IJobFactory, JobFactory>();
            //services.AddSingleton(typeof(IJobFactory), new JobFactory(services.BuildServiceProvider()));
            //services.AddSingleton(new JobFactory(services.BuildServiceProvider()));
            //services.AddTransient<LoggingProvider>();

            //Startup and Middleware
            //services.AddTransient<IStartupFilter, QuartzStartupFilter>();
        }
 /// <summary>
 ///
 /// </summary>
 /// <param name="options"></param>
 public LogRepositorieFactory(IOptions <QuartzOptions> options)
 {
     quartzOptions = options?.Value ?? new QuartzOptions()
     {
         { "quartz.jobStore.dataSource", "default" },
         { "quartz.jobStore.tablePrefix", "QRTZ_" }
     };
 }
        public static void UseInMemoryStorage(this IServiceCollection services, QuartzOptions inMemoryQuartzOptions)
        {
            if (inMemoryQuartzOptions.SchedulerName.IsMissing())
            {
                inMemoryQuartzOptions.SchedulerName = HybridConsts.DefaultSchedulerName;
            }
            IScheduler scheduler = new StdSchedulerFactory(SetProperties(inMemoryQuartzOptions)).GetScheduler().Result;

            services.AddSingleton(scheduler);
        }
        public QuartzManager(ILogger <QuartzService> logger, IServiceProvider serviceProvider, QuartzRepository yunYingRepository, IOptions <QuartzOptions> options)
        {
            _logger            = logger;
            _yunYingRepository = yunYingRepository;
            _quartzOptions     = options.Value;
            //配置AdoJobStore的集群功能
            //1-所有实例都必须使用不同的属性文件,因为它们的实例ID必须不同,但是所有其他属性都应该相同。
            //2-您可能应该从一组“新”表开始(假设您由于其他测试混合了数据,具有集群的非集群设置可能很糟糕。)
            //3-尝试在它们运行时杀死其中一个集群实例,然后看看其余实例将恢复正在进行的作业。请注意,默认情况下,检测到故障可能需要15秒钟左右(最少7.5秒)的时间设置
            //4-也可以尝试使用/不使用已注册的shutdown-hook插件来运行它调度程序。(quartz.plugins.management.ShutdownHookPlugin)。
            //5-注意:切勿在单独的计算机上运行群集,除非它们在不同的计算机上运行使用某种形式的时间同步服务(守护程序)来同步时钟。

            if (_quartzOptions.Clustered)
            {
                //配置持久化-集群
                NameValueCollection properties = new NameValueCollection();
                //开启集群
                properties["quartz.jobStore.clustered"] = _quartzOptions.Clustered ? "true" : "false";
                //调度标识名,集群中每一个实例都必须使用相同的名称
                properties["quartz.scheduler.instanceName"] = string.IsNullOrEmpty(_quartzOptions.InstanceName) ? "TaskScheduler" : _quartzOptions.InstanceName;
                //ID设置为自动获取 每一个必须不同
                properties["quartz.scheduler.instanceId"] = string.IsNullOrEmpty(_quartzOptions.InstanceId) ? "AUTO" : _quartzOptions.InstanceId;
                //这个时间大于10000(10秒)会导致WithMisfireHandlingInstructionDoNothing不生效。
                properties["quartz.jobStore.misfireThreshold"] = "5000";
                //properties["quartz.threadPool.type"] = "Quartz.Simpl.SimpleThreadPool, Quartz";
                //线程池个数
                properties["quartz.threadPool.threadCount"] = string.IsNullOrEmpty(_quartzOptions.ThreadCount) ? "20" : _quartzOptions.ThreadCount;
                //存储类型(数据保存方式为持久化)
                properties["quartz.jobStore.type"] = string.IsNullOrEmpty(_quartzOptions.JobStoreType) ? "Quartz.Impl.AdoJobStore.JobStoreTX, Quartz" : _quartzOptions.JobStoreType;
                //设置为TRUE不会出现序列化非字符串类到 BLOB 时产生的类版本问题
                //properties["quartz.jobStore.useProperties"] = "true";
                //数据库别名(任意)
                properties["quartz.jobStore.dataSource"] = "myDS";
                //表明前缀
                properties["quartz.jobStore.tablePrefix"] = string.IsNullOrEmpty(_quartzOptions.TablePrefix) ? "QRTZ_" : _quartzOptions.TablePrefix;
                //使用Sqlserver的Ado操作代理类
                properties["quartz.jobStore.driverDelegateType"] = string.IsNullOrEmpty(_quartzOptions.DriverDelegateType) ? "Quartz.Impl.AdoJobStore.SqlServerDelegate, Quartz" : _quartzOptions.DriverDelegateType;
                //连接字符串
                properties["quartz.dataSource.myDS.connectionString"] = _quartzOptions.ConnectionString;
                //sqlserver版本
                properties["quartz.dataSource.myDS.provider"] = string.IsNullOrEmpty(_quartzOptions.Provider) ? "SqlServer" : _quartzOptions.Provider;
                //序列化类型(json)
                properties["quartz.serializer.type"] = string.IsNullOrEmpty(_quartzOptions.SerializerType) ? "json" : _quartzOptions.SerializerType;

                //创建作业调度池
                _scheduler = new StdSchedulerFactory(properties).GetScheduler().Result;
            }
            else
            {
                //创建作业调度池
                _scheduler = new StdSchedulerFactory().GetScheduler().Result;
            }
            //实现Job的注入(quartz默认情况下,它仅支持无参数构造函数)
            _scheduler.JobFactory = new ServiceCollectionJobFactory(serviceProvider);
        }
Beispiel #5
0
        public static QuartzOptions UseDashboard(this QuartzOptions quartzOptions, Action <DashboardQuartzOptions> options)
        {
            if (options == null)
            {
                throw new ArgumentNullException(nameof(options));
            }

            quartzOptions.RegisterExtension(new DashboardQuartzOptionsExtension(options));

            return(quartzOptions);
        }
Beispiel #6
0
        public void UseQuartz_RegistersJobDetails()
        {
            // Arrange
            var options       = new QuartzOptions();
            var configuration = new OpenIddictQuartzConfiguration();

            // Act
            configuration.Configure(options);

            // Assert
            Assert.Contains(options.JobDetails, job => job.Key.Equals(OpenIddictQuartzJob.Identity));
        }
Beispiel #7
0
 public HomeController(ILogger <HomeController> logger,
                       ISchedulerFactory schedulerFactory,
                       IDistributedCache distributedCache,
                       IOptions <QuartzOptions> quartzOptions,
                       IFluentEmail fluentEmail)
 {
     _logger           = logger;
     _scheduler        = schedulerFactory.GetScheduler().Result;
     _distributedCache = distributedCache;
     _quartzOptions    = quartzOptions.Value;
     _fluentEmail      = fluentEmail;
 }
Beispiel #8
0
        public override IServiceCollection AddServices(IServiceCollection services)
        {
            IConfiguration configuration = services.GetConfiguration();
            QuartzOptions  quartzOptions = configuration.GetSection("Hybrid:Quartz").Get <QuartzOptions>();

            _enabled = quartzOptions.IsEnabled;
            // _useDashboard = quartzOptions.UseDashboard;
            if (!_enabled)
            {
                return(services);
            }
            if (string.IsNullOrWhiteSpace(quartzOptions.TablePrefix))
            {
                quartzOptions.TablePrefix = AdoConstants.DefaultTablePrefix;
            }
            if (string.IsNullOrWhiteSpace(quartzOptions.SchedulerName))
            {
                quartzOptions.SchedulerName = HybridConsts.DefaultSchedulerName;
            }
            services.AddSingleton(quartzOptions);
            if (quartzOptions.StorageType.Equals(QuartzStorageType.InMemory))
            {
                services.UseInMemoryStorage(quartzOptions);
            }
            else if (quartzOptions.StorageType.Equals(QuartzStorageType.SqlServer))
            {
                services.UseSqlServer(quartzOptions);
            }
            else if (quartzOptions.StorageType.Equals(QuartzStorageType.MySql))
            {
                services.UseMySql(quartzOptions);
            }
            else
            {
                throw new HybridException("配置文件中Quartz节点的StorageType错误");
            }

            //初始化定时任务查找器
            services.TryAddSingleton <IJobTypeFinder, JobTypeFinder>();
            //注入所有IJob
            services.InitializeJobs();

            services.AddTransient <ISchedulerFactory, StdSchedulerFactory>();
            services.AddSingleton <IJobFactory, JobFactory>();
            //services.AddSingleton(typeof(IJobFactory), new JobFactory(services.BuildServiceProvider()));
            //services.AddSingleton(new JobFactory(services.BuildServiceProvider()));
            //services.AddTransient<LoggingProvider>();

            UseQuartzUI(services);

            return(base.AddServices(services));
        }
Beispiel #9
0
        public void UseQuartz_RegistersJobDetails()
        {
            // Arrange
            var options       = new QuartzOptions();
            var configuration = new OpenIddictQuartzConfiguration();

            // Act
            configuration.Configure(options);

            // Assert
            // TODO: uncomment when JobDetails and Triggers are publicly exposed.
            // Assert.Contains(options.JobDetails, job => job.Key.Equals(OpenIddictQuartzJob.Identity));
        }
Beispiel #10
0
        private static NameValueCollection SetProperties(QuartzOptions mySqlQuartzOptions)
        {
            var properties = new NameValueCollection();

            // properties.Set(StdSchedulerFactory.PropertySchedulerName, mySqlQuartzOptions.SchedulerName);
            // 实例名称
            properties.Set("quartz.scheduler.instanceName", mySqlQuartzOptions.SchedulerName);
            // 实例Id
            // 线程池
            properties.Set("quartz.threadPool.type", "Quartz.Simpl.SimpleThreadPool, Quartz");
            // 设置线程池的最大线程数量
            properties.Set("quartz.threadPool.threadCount", mySqlQuartzOptions.ThreadCount.ToString());
            // 设置作业中每个线程的优先级,可取 System.Threading.ThreadPriority 中的枚举
            properties.Set("quartz.threadPool.threadPriority", mySqlQuartzOptions.ThreadPriority.ToString());

            properties.Set(StdSchedulerFactory.PropertyJobStoreType, "Quartz.Impl.AdoJobStore.JobStoreTX, Quartz");

            properties.Set("quartz.jobStore.useProperties", "true");
            properties.Set("quartz.jobStore.dataSource", "default");
            properties.Set("quartz.dataSource.default.connectionString", mySqlQuartzOptions.ConnectionStringOrCacheName);
            properties.Set("quartz.dataSource.default.provider", "MySql");
            properties.Set("quartz.jobStore.driverDelegateType", "Quartz.Impl.AdoJobStore.MySQLDelegate, Quartz");
            properties.Set("quartz.jobStore.tablePrefix", mySqlQuartzOptions.TablePrefix);
            properties.Set("quartz.serializer.type", mySqlQuartzOptions.SerializerType.ToString());

            if (mySqlQuartzOptions.IsClustered)
            {
                //是否集群,集群模式下要设置为true
                properties["quartz.jobStore.clustered"] = "true";
                //集群模式下设置为auto,自动获取实例的Id,集群下一定要id不一样,不然不会自动恢复
                properties["quartz.scheduler.instanceId"] = "AUTO";
            }

            if (mySqlQuartzOptions.IsUseHistoryPlugin)
            {
                // 加载插件
                // properties.Set("quartz.plugin.自定义名称.type","命名空间.类名,程序集名称");
                properties.Set("quartz.plugin.DatabaseExecutionHistory.type", "Hybrid.Quartz.Plugins.History.DatabaseExecutionHistoryPlugin,Hybrid.Quartz");
                properties.Set("quartz.plugin.DatabaseExecutionHistory.dataSource", "default");
                properties.Set("quartz.plugin.DatabaseExecutionHistory.driverDelegateType", "Quartz.Impl.AdoJobStore.MySQLDelegate, Quartz");
                properties.Set("quartz.plugin.DatabaseExecutionHistory.storeType", "Hybrid.Quartz.Plugins.History.DatabaseExecutionHistoryStore, Hybrid.Quartz");
                properties.Set("quartz.plugin.DatabaseExecutionHistory.tablePrefix", mySqlQuartzOptions.TablePrefix);
                properties.Set("quartz.plugin.DatabaseExecutionHistory.provider", "MySql");
            }

            return(properties);
        }
Beispiel #11
0
        /// <summary>
        /// 获取Quartz属性
        /// </summary>
        /// <returns></returns>
        private NameValueCollection GetQuartzProps(QuartzOptions options, DbOptions dbOptions)
        {
            var quartzProps     = new NameValueCollection();
            var quartzDbOptions = dbOptions.Modules.FirstOrDefault(m => m.Name.EqualsIgnoreCase("quartz"));

            if (quartzDbOptions != null)
            {
                quartzProps["quartz.scheduler.instanceName"]              = options.InstanceName;
                quartzProps["quartz.jobStore.type"]                       = "Quartz.Impl.AdoJobStore.JobStoreTX,Quartz";
                quartzProps["quartz.jobStore.driverDelegateType"]         = "Quartz.Impl.AdoJobStore.StdAdoDelegate,Quartz";
                quartzProps["quartz.jobStore.tablePrefix"]                = options.TablePrefix;
                quartzProps["quartz.jobStore.dataSource"]                 = "default";
                quartzProps["quartz.dataSource.default.connectionString"] = quartzDbOptions.ConnectionString;
                quartzProps["quartz.dataSource.default.provider"]         = GetProvider(dbOptions.Dialect);
                quartzProps["quartz.serializer.type"]                     = options.SerializerType;
            }

            return(quartzProps);
        }
        private static NameValueCollection SetProperties(QuartzOptions inMemoryQuartzOptions)
        {
            var properties = new NameValueCollection();

            // properties.Set(StdSchedulerFactory.PropertySchedulerName, inMemoryQuartzOptions.SchedulerName);
            // 实例名称
            properties.Set("quartz.scheduler.instanceName", inMemoryQuartzOptions.SchedulerName);
            // 实例Id
            // 线程池
            properties.Set("quartz.threadPool.type", "Quartz.Simpl.SimpleThreadPool, Quartz");
            // 设置线程池的最大线程数量
            properties.Set("quartz.threadPool.threadCount", inMemoryQuartzOptions.ThreadCount.ToString());
            // 设置作业中每个线程的优先级,可取 System.Threading.ThreadPriority 中的枚举
            properties.Set("quartz.threadPool.threadPriority", inMemoryQuartzOptions.ThreadPriority.ToString());

            properties.Set(StdSchedulerFactory.PropertyJobStoreType, "Quartz.Simpl.RAMJobStore, Quartz");
            //properties.Set(QuartzConsts.PropertySerializerType, inMemoryQuartzOptions.SerializerType.ToString());
            //properties.Remove(QuartzConsts.PropertyDataSourceDatabaseConnectionString);
            //properties.Remove(QuartzConsts.PropertyDataSourceDatabaseProvider);
            //properties.Remove(QuartzConsts.PropertyJobStoreDataSource);
            //properties.Remove(QuartzConsts.PropertyJobStoreDriverDelegateType);
            //properties.Remove(QuartzConsts.PropertyJobStoreTablePrefix);
            //properties.Remove(QuartzConsts.PropertyJobStoreUseProperties);

            //if (inMemoryQuartzOptions.IsClustered)
            //{
            //    //是否集群,集群模式下要设置为true
            //    properties["quartz.jobStore.clustered"] = "true";
            //    //集群模式下设置为auto,自动获取实例的Id,集群下一定要id不一样,不然不会自动恢复
            //    properties["quartz.scheduler.instanceId"] = "AUTO";
            //}

            if (inMemoryQuartzOptions.IsUseHistoryPlugin)
            {
                // 加载插件
                // properties.Set("quartz.plugin.自定义名称.type","命名空间.类名,程序集名称");
                properties.Set("quartz.plugin.InMemoryExecutionHistory.type", "Hybrid.Quartz.Plugins.History.InMemoryExecutionHistoryPlugin, Hybrid.Quartz");
                properties.Set("quartz.plugin.InMemoryExecutionHistory.storeType", "Hybrid.Quartz.Plugins.History.InMemoryExecutionHistoryStore, Hybrid.Quartz");
            }

            return(properties);
        }
Beispiel #13
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddOptions();

            // IMPORTANT: Do not forget to register the job itself so it can be later resolved by the JobFactory
            services.AddTransient <SampleJob>();
            services.AddTransient <IJobFactory, JobFactory>();
            services.AddSingleton(provider =>
            {
                var option           = new QuartzOptions(Configuration);
                var sf               = new StdSchedulerFactory(option.ToProperties());
                var scheduler        = sf.GetScheduler().Result;
                scheduler.JobFactory = provider.GetService <IJobFactory>();
                return(scheduler);
            });

            services.AddHostedService <SchedulingHostedService>();

            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
        }
Beispiel #14
0
 public static QuartzOptions UseDashboard(this QuartzOptions quartzOptions)
 {
     return(quartzOptions.UseDashboard(opt => { }));
 }
Beispiel #15
0
        private static NameValueCollection SetProperties(QuartzOptions sqlServerQuartzOptions)
        {
            var properties = new NameValueCollection();

            // 调度名称
            // properties.Set(StdSchedulerFactory.PropertySchedulerName, sqlServerQuartzOptions.SchedulerName);
            // 实例名称
            properties.Set("quartz.scheduler.instanceName", sqlServerQuartzOptions.SchedulerName);
            // 实例Id
            // 线程池
            properties.Set("quartz.threadPool.type", "Quartz.Simpl.SimpleThreadPool, Quartz");
            // 设置线程池的最大线程数量
            properties.Set("quartz.threadPool.threadCount", sqlServerQuartzOptions.ThreadCount.ToString());
            // 设置作业中每个线程的优先级,可取 System.Threading.ThreadPriority 中的枚举
            properties.Set("quartz.threadPool.threadPriority", sqlServerQuartzOptions.ThreadPriority.ToString());

            // 数据连接字符串
            properties.Set("quartz.dataSource.myDS.connectionString", sqlServerQuartzOptions.ConnectionStringOrCacheName);
            // 数据库类型
            properties.Set("quartz.dataSource.myDS.provider", "SqlServer");
            // 设置存储类型
            properties.Set(StdSchedulerFactory.PropertyJobStoreType, "Quartz.Impl.AdoJobStore.JobStoreTX, Quartz");
            // 驱动类型
            properties.Set("quartz.jobStore.driverDelegateType", "Quartz.Impl.AdoJobStore.StdAdoDelegate, Quartz");
            // 数据源名称
            properties.Set("quartz.jobStore.dataSource", "myDS");
            // JobDataMaps 中的值只能是字符串,具体可以看官方推荐这样设置的原因
            // 您可以并且应该使用最新版本的驱动程序(如果有更新的话),只需创建程序集绑定重定向即可
            // 如果您的调度程序非常忙(即几乎总是执行与线程池大小相同的作业数),那么您可能应该将数据源中的连接数设置为线程池大小的大约 + 1。通常在ADO.NET连接字符串中配置它 - 有关详细信息,请参见驱动程序实现。
            // 可以将“quartz.jobStore.useProperties”配置参数设置为“ true”(默认为false),以指示AdoJobStore JobDataMaps中的所有值都是字符串,因此可以作为名称 - 值对存储,而不是存储BLOB列中序列化形式的更复杂对象。从长远来看,这样做更加安全,因为可以避免将非String类序列化为BLOB时出现的类版本控制问题。
            properties.Set("quartz.jobStore.useProperties", "true");
            // 表前缀
            properties.Set("quartz.jobStore.tablePrefix", sqlServerQuartzOptions.TablePrefix);
            // 数据存储序列化方式
            properties.Set("quartz.serializer.type", sqlServerQuartzOptions.SerializerType.ToString());

            if (sqlServerQuartzOptions.IsClustered)
            {
                //是否集群,集群模式下要设置为true
                properties["quartz.jobStore.clustered"] = "true";
                //集群模式下设置为auto,自动获取实例的Id,集群下一定要id不一样,不然不会自动恢复
                properties["quartz.scheduler.instanceId"] = "AUTO";
                //
                if (sqlServerQuartzOptions.IsUseSelectWithLockSQL)
                {
                    properties.Set("quartz.jobStore.selectWithLockSQL", $"SELECT * FROM {sqlServerQuartzOptions.TablePrefix}LOCKS WITH(UPDLOCK) WHERE SCHED_NAME = @schedulerName AND LOCK_NAME = @lockName");
                }
            }

            // 加载插件
            if (sqlServerQuartzOptions.IsUseHistoryPlugin)
            {
                // 加载获取历史记录插件
                // properties.Set("quartz.plugin.自定义名称.type","命名空间.类名,程序集名称");
                properties.Set("quartz.plugin.DatabaseExecutionHistory.type", "Hybrid.Quartz.Plugins.History.DatabaseExecutionHistoryPlugin,Hybrid.Quartz");
                properties.Set("quartz.plugin.DatabaseExecutionHistory.dataSource", "myDS");
                properties.Set("quartz.plugin.DatabaseExecutionHistory.driverDelegateType", "Quartz.Impl.AdoJobStore.StdAdoDelegate, Quartz");
                properties.Set("quartz.plugin.DatabaseExecutionHistory.storeType", "Hybrid.Quartz.Plugins.History.DatabaseExecutionHistoryStore, Hybrid.Quartz");
                properties.Set("quartz.plugin.DatabaseExecutionHistory.tablePrefix", sqlServerQuartzOptions.TablePrefix);
                properties.Set("quartz.plugin.DatabaseExecutionHistory.provider", "SqlServer");
            }

            return(properties);
            //["quartz.scheduler.instanceName"] = "TestScheduler",
            //["quartz.scheduler.instanceId"] = "instance_one",
            //["quartz.threadPool.type"] = "Quartz.Simpl.SimpleThreadPool, Quartz",
            //["quartz.threadPool.threadCount"] = "5",
            //["quartz.jobStore.misfireThreshold"] = "60000",
            //["quartz.jobStore.type"] = "Quartz.Impl.AdoJobStore.JobStoreTX, Quartz",
            //["quartz.jobStore.useProperties"] = "false",
            //["quartz.jobStore.dataSource"] = "default",
            //["quartz.jobStore.tablePrefix"] = "QRTZ_",
            //["quartz.jobStore.clustered"] = "true",
            //["quartz.jobStore.driverDelegateType"] = "Quartz.Impl.AdoJobStore.SqlServerDelegate, Quartz",
            //["quartz.dataSource.default.connectionString"] = TestConstants.SqlServerConnectionString,
            //["quartz.dataSource.default.provider"] = TestConstants.DefaultSqlServerProvider,
            //["quartz.serializer.type"] = "json"
            //initialization plugin handles our xml reading, without it defaults are used
            //quartz.plugin.xml.type = Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin, Quartz
            //quartz.plugin.xml.fileNames = ~/ quartz_jobs.xml
        }
 public TaskLogger(IJobLogRepository repository, QuartzOptions options)
 {
     _repository = repository;
     _options    = options;
 }
Beispiel #17
0
 public TaskLogger(IJobLogService service, QuartzOptions options)
 {
     _service = service;
     _options = options;
 }
Beispiel #18
0
 public QuartzStartup(IOptions <QuartzOptions> options, IApplicationLifetime lifetime)
 {
     _quartzOptions = options.Value;
     _lifeTime      = lifetime;
 }
 public JobLogger(IJobLogRepository repository, IOptionsMonitor <QuartzOptions> optionsMonitor)
 {
     _repository = repository;
     _options    = optionsMonitor.CurrentValue;
 }
Beispiel #20
0
        public static void UseSqlServer(this IServiceCollection services, QuartzOptions sqlServerQuartzOptions)
        {
            IScheduler scheduler = new StdSchedulerFactory(SetProperties(sqlServerQuartzOptions)).GetScheduler().Result;

            services.AddSingleton(scheduler);
        }