From 979eb4a8428c730aa21e49ee6cb012e7f280a180 Mon Sep 17 00:00:00 2001 From: Oscar Hinton Date: Fri, 12 Feb 2021 13:49:11 +0100 Subject: [PATCH] Run Quartz in clustered mode (#1123) --- src/Admin/Jobs/JobsHostedService.cs | 7 +----- src/Api/Jobs/JobsHostedService.cs | 4 +++- src/Billing/Jobs/JobsHostedService.cs | 6 +---- src/Core/GlobalSettings.cs | 10 ++++++++ src/Core/Jobs/BaseJobsHostedService.cs | 26 ++++++++++++++++++--- src/Notifications/Jobs/JobsHostedService.cs | 4 +++- 6 files changed, 41 insertions(+), 16 deletions(-) diff --git a/src/Admin/Jobs/JobsHostedService.cs b/src/Admin/Jobs/JobsHostedService.cs index ab66cd96dd..eee24f52b8 100644 --- a/src/Admin/Jobs/JobsHostedService.cs +++ b/src/Admin/Jobs/JobsHostedService.cs @@ -13,17 +13,12 @@ namespace Bit.Admin.Jobs { public class JobsHostedService : BaseJobsHostedService { - private readonly GlobalSettings _globalSettings; - public JobsHostedService( GlobalSettings globalSettings, IServiceProvider serviceProvider, ILogger logger, ILogger listenerLogger) - : base(serviceProvider, logger, listenerLogger) - { - _globalSettings = globalSettings; - } + : base(globalSettings, serviceProvider, logger, listenerLogger) { } public override async Task StartAsync(CancellationToken cancellationToken) { diff --git a/src/Api/Jobs/JobsHostedService.cs b/src/Api/Jobs/JobsHostedService.cs index 4fa9be7f00..aba60a55b4 100644 --- a/src/Api/Jobs/JobsHostedService.cs +++ b/src/Api/Jobs/JobsHostedService.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using Bit.Core; using Bit.Core.Jobs; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; @@ -12,10 +13,11 @@ namespace Bit.Api.Jobs public class JobsHostedService : BaseJobsHostedService { public JobsHostedService( + GlobalSettings globalSettings, IServiceProvider serviceProvider, ILogger logger, ILogger listenerLogger) - : base(serviceProvider, logger, listenerLogger) { } + : base(globalSettings, serviceProvider, logger, listenerLogger) { } public override async Task StartAsync(CancellationToken cancellationToken) { diff --git a/src/Billing/Jobs/JobsHostedService.cs b/src/Billing/Jobs/JobsHostedService.cs index 706517856b..f02515b30f 100644 --- a/src/Billing/Jobs/JobsHostedService.cs +++ b/src/Billing/Jobs/JobsHostedService.cs @@ -13,16 +13,12 @@ namespace Bit.Billing.Jobs { public class JobsHostedService : BaseJobsHostedService { - private readonly GlobalSettings _globalSettings; - public JobsHostedService( GlobalSettings globalSettings, IServiceProvider serviceProvider, ILogger logger, ILogger listenerLogger) - : base(serviceProvider, logger, listenerLogger) { - _globalSettings = globalSettings; - } + : base(globalSettings, serviceProvider, logger, listenerLogger) {} public override async Task StartAsync(CancellationToken cancellationToken) { diff --git a/src/Core/GlobalSettings.cs b/src/Core/GlobalSettings.cs index b5c2582332..da2c59a77e 100644 --- a/src/Core/GlobalSettings.cs +++ b/src/Core/GlobalSettings.cs @@ -67,6 +67,7 @@ namespace Bit.Core { private string _connectionString; private string _readOnlyConnectionString; + private string _jobSchedulerConnectionString; public string ConnectionString { @@ -86,6 +87,15 @@ namespace Bit.Core _readOnlyConnectionString = value.Trim('"'); } } + + public string JobSchedulerConnectionString + { + get => _jobSchedulerConnectionString; + set + { + _jobSchedulerConnectionString = value.Trim('"'); + } + } } public class ConnectionStringSettings diff --git a/src/Core/Jobs/BaseJobsHostedService.cs b/src/Core/Jobs/BaseJobsHostedService.cs index 18c2aed359..07d22f370e 100644 --- a/src/Core/Jobs/BaseJobsHostedService.cs +++ b/src/Core/Jobs/BaseJobsHostedService.cs @@ -18,8 +18,10 @@ namespace Bit.Core.Jobs protected readonly ILogger _logger; private IScheduler _scheduler; + protected GlobalSettings _globalSettings; public BaseJobsHostedService( + GlobalSettings globalSettings, IServiceProvider serviceProvider, ILogger logger, ILogger listenerLogger) @@ -27,16 +29,34 @@ namespace Bit.Core.Jobs _serviceProvider = serviceProvider; _logger = logger; _listenerLogger = listenerLogger; + _globalSettings = globalSettings; } public IEnumerable> Jobs { get; protected set; } public virtual async Task StartAsync(CancellationToken cancellationToken) { - var factory = new StdSchedulerFactory(new NameValueCollection + var props = new NameValueCollection { - { "quartz.serializer.type", "binary" } - }); + {"quartz.serializer.type", "binary"}, + }; + + if (!string.IsNullOrEmpty(_globalSettings.SqlServer.JobSchedulerConnectionString)) + { + // Ensure each project has a unique instanceName + props.Add("quartz.scheduler.instanceName", GetType().FullName); + props.Add("quartz.scheduler.instanceId", "AUTO"); + props.Add("quartz.jobStore.type", "Quartz.Impl.AdoJobStore.JobStoreTX"); + props.Add("quartz.jobStore.driverDelegateType", "Quartz.Impl.AdoJobStore.SqlServerDelegate"); + props.Add("quartz.jobStore.useProperties", "true"); + props.Add("quartz.jobStore.dataSource", "default"); + props.Add("quartz.jobStore.tablePrefix", "QRTZ_"); + props.Add("quartz.jobStore.clustered", "true"); + props.Add("quartz.dataSource.default.provider", "SqlServer"); + props.Add("quartz.dataSource.default.connectionString", _globalSettings.SqlServer.JobSchedulerConnectionString); + } + + var factory = new StdSchedulerFactory(props); _scheduler = await factory.GetScheduler(cancellationToken); _scheduler.JobFactory = new JobFactory(_serviceProvider); _scheduler.ListenerManager.AddJobListener(new JobListener(_listenerLogger), diff --git a/src/Notifications/Jobs/JobsHostedService.cs b/src/Notifications/Jobs/JobsHostedService.cs index 2ce6d347b0..5d9570aab5 100644 --- a/src/Notifications/Jobs/JobsHostedService.cs +++ b/src/Notifications/Jobs/JobsHostedService.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using Bit.Core; using Bit.Core.Jobs; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; @@ -12,10 +13,11 @@ namespace Bit.Notifications.Jobs public class JobsHostedService : BaseJobsHostedService { public JobsHostedService( + GlobalSettings globalSettings, IServiceProvider serviceProvider, ILogger logger, ILogger listenerLogger) - : base(serviceProvider, logger, listenerLogger) { } + : base(globalSettings, serviceProvider, logger, listenerLogger) { } public override async Task StartAsync(CancellationToken cancellationToken) {