diff --git a/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/AbpBackgroundJobOptions.cs b/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/AbpBackgroundJobOptions.cs index a16bc418a7..6ca409ec56 100644 --- a/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/AbpBackgroundJobOptions.cs +++ b/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/AbpBackgroundJobOptions.cs @@ -8,8 +8,7 @@ namespace Volo.Abp.BackgroundJobs { private readonly Dictionary _jobConfigurationsByArgsType; private readonly Dictionary _jobConfigurationsByName; - - //TODO: Implement for all providers! (Hangfire does not implement yet) + /// /// Default: true. /// diff --git a/framework/src/Volo.Abp.BackgroundJobs.HangFire/Volo/Abp/BackgroundJobs/Hangfire/AbpBackgroundJobsHangfireModule.cs b/framework/src/Volo.Abp.BackgroundJobs.HangFire/Volo/Abp/BackgroundJobs/Hangfire/AbpBackgroundJobsHangfireModule.cs index 066dccc28f..8e6802e751 100644 --- a/framework/src/Volo.Abp.BackgroundJobs.HangFire/Volo/Abp/BackgroundJobs/Hangfire/AbpBackgroundJobsHangfireModule.cs +++ b/framework/src/Volo.Abp.BackgroundJobs.HangFire/Volo/Abp/BackgroundJobs/Hangfire/AbpBackgroundJobsHangfireModule.cs @@ -1,4 +1,8 @@ -using Volo.Abp.Hangfire; +using System; +using Hangfire; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Volo.Abp.Hangfire; using Volo.Abp.Modularity; namespace Volo.Abp.BackgroundJobs.Hangfire @@ -6,9 +10,23 @@ namespace Volo.Abp.BackgroundJobs.Hangfire [DependsOn( typeof(AbpBackgroundJobsAbstractionsModule), typeof(AbpHangfireModule) - )] + )] public class AbpBackgroundJobsHangfireModule : AbpModule { + public override void OnPreApplicationInitialization(ApplicationInitializationContext context) + { + var options = context.ServiceProvider.GetRequiredService>().Value; + if (!options.IsJobExecutionEnabled) + { + var hangfireOptions = context.ServiceProvider.GetRequiredService>().Value; + hangfireOptions.BackgroundJobServerFactory = CreateOnlyEnqueueJobServer; + } + } + private BackgroundJobServer CreateOnlyEnqueueJobServer(IServiceProvider serviceProvider) + { + serviceProvider.GetRequiredService(); + return null; + } } -} +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.BackgroundJobs.HangFire/Volo/Abp/BackgroundJobs/Hangfire/HangfireBackgroundJobManager.cs b/framework/src/Volo.Abp.BackgroundJobs.HangFire/Volo/Abp/BackgroundJobs/Hangfire/HangfireBackgroundJobManager.cs index 48b2dea666..8b6c6f89f7 100644 --- a/framework/src/Volo.Abp.BackgroundJobs.HangFire/Volo/Abp/BackgroundJobs/Hangfire/HangfireBackgroundJobManager.cs +++ b/framework/src/Volo.Abp.BackgroundJobs.HangFire/Volo/Abp/BackgroundJobs/Hangfire/HangfireBackgroundJobManager.cs @@ -8,7 +8,7 @@ namespace Volo.Abp.BackgroundJobs.Hangfire [Dependency(ReplaceServices = true)] public class HangfireBackgroundJobManager : IBackgroundJobManager, ITransientDependency { - public Task EnqueueAsync(TArgs args, BackgroundJobPriority priority = BackgroundJobPriority.Normal, + public virtual Task EnqueueAsync(TArgs args, BackgroundJobPriority priority = BackgroundJobPriority.Normal, TimeSpan? delay = null) { if (!delay.HasValue) diff --git a/framework/src/Volo.Abp.BackgroundJobs.HangFire/Volo/Abp/BackgroundJobs/Hangfire/HangfireJobExecutionAdapter.cs b/framework/src/Volo.Abp.BackgroundJobs.HangFire/Volo/Abp/BackgroundJobs/Hangfire/HangfireJobExecutionAdapter.cs index 676a3eaafc..41398b5bb6 100644 --- a/framework/src/Volo.Abp.BackgroundJobs.HangFire/Volo/Abp/BackgroundJobs/Hangfire/HangfireJobExecutionAdapter.cs +++ b/framework/src/Volo.Abp.BackgroundJobs.HangFire/Volo/Abp/BackgroundJobs/Hangfire/HangfireJobExecutionAdapter.cs @@ -1,4 +1,6 @@ using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; using Volo.Abp.Threading; @@ -6,22 +8,31 @@ namespace Volo.Abp.BackgroundJobs.Hangfire { public class HangfireJobExecutionAdapter { + public ILogger> Logger { get; set; } + protected AbpBackgroundJobOptions Options { get; } protected IServiceScopeFactory ServiceScopeFactory { get; } protected IBackgroundJobExecuter JobExecuter { get; } public HangfireJobExecutionAdapter( - IOptions options, - IBackgroundJobExecuter jobExecuter, + IOptions options, + IBackgroundJobExecuter jobExecuter, IServiceScopeFactory serviceScopeFactory) { JobExecuter = jobExecuter; ServiceScopeFactory = serviceScopeFactory; Options = options.Value; + Logger = NullLogger>.Instance; } public void Execute(TArgs args) { + if (!Options.IsJobExecutionEnabled) + { + Logger.LogWarning("Background jobs system is disabled"); + return; + } + using (var scope = ServiceScopeFactory.CreateScope()) { var jobType = Options.GetJob(typeof(TArgs)).JobType; @@ -30,4 +41,4 @@ namespace Volo.Abp.BackgroundJobs.Hangfire } } } -} +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.BackgroundJobs.Quartz/Volo/Abp/BackgroundJobs/Quartz/AbpBackgroundJobQuartzOptions.cs b/framework/src/Volo.Abp.BackgroundJobs.Quartz/Volo/Abp/BackgroundJobs/Quartz/AbpBackgroundJobQuartzOptions.cs new file mode 100644 index 0000000000..e9ecb41c57 --- /dev/null +++ b/framework/src/Volo.Abp.BackgroundJobs.Quartz/Volo/Abp/BackgroundJobs/Quartz/AbpBackgroundJobQuartzOptions.cs @@ -0,0 +1,46 @@ +using System; +using System.Threading.Tasks; +using JetBrains.Annotations; +using Quartz; + +namespace Volo.Abp.BackgroundJobs.Quartz +{ + public class AbpBackgroundJobQuartzOptions + { + public int RetryCount { get; set; } + + public int RetryIntervalMillisecond { get; set; } + + + [NotNull] + public Func RetryStrategy + { + get => _retryStrategy; + set => _retryStrategy = Check.NotNull(value, nameof(value)); + } + private Func _retryStrategy; + + public AbpBackgroundJobQuartzOptions() + { + RetryCount = 3; + RetryIntervalMillisecond = 3000; + _retryStrategy = DefaultRetryStrategy; + } + + private async Task DefaultRetryStrategy(int retryIndex, IJobExecutionContext executionContext, JobExecutionException exception) + { + exception.RefireImmediately = true; + + var retryCount = executionContext.JobDetail.JobDataMap.GetIntValue(QuartzBackgroundJobManager.JobDataPrefix+ nameof(RetryCount)); + if (retryIndex > retryCount) + { + exception.RefireImmediately = false; + exception.UnscheduleAllTriggers = true; + return; + } + + var retryInterval = executionContext.JobDetail.JobDataMap.GetIntValue(QuartzBackgroundJobManager.JobDataPrefix+ nameof(RetryIntervalMillisecond)); + await Task.Delay(retryInterval); + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.BackgroundJobs.Quartz/Volo/Abp/BackgroundJobs/Quartz/AbpBackgroundJobsQuartzModule.cs b/framework/src/Volo.Abp.BackgroundJobs.Quartz/Volo/Abp/BackgroundJobs/Quartz/AbpBackgroundJobsQuartzModule.cs index d5f84ed91e..4c9366e93f 100644 --- a/framework/src/Volo.Abp.BackgroundJobs.Quartz/Volo/Abp/BackgroundJobs/Quartz/AbpBackgroundJobsQuartzModule.cs +++ b/framework/src/Volo.Abp.BackgroundJobs.Quartz/Volo/Abp/BackgroundJobs/Quartz/AbpBackgroundJobsQuartzModule.cs @@ -1,4 +1,6 @@ -using Microsoft.Extensions.DependencyInjection; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; using Volo.Abp.Modularity; using Volo.Abp.Quartz; @@ -8,11 +10,21 @@ namespace Volo.Abp.BackgroundJobs.Quartz typeof(AbpBackgroundJobsAbstractionsModule), typeof(AbpQuartzModule) )] - public class AbpBackgroundJobsQuartzModule :AbpModule + public class AbpBackgroundJobsQuartzModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { context.Services.AddTransient(typeof(QuartzJobExecutionAdapter<>)); } + + public override void OnPreApplicationInitialization(ApplicationInitializationContext context) + { + var options = context.ServiceProvider.GetService>().Value; + if (!options.IsJobExecutionEnabled) + { + var quartzOptions = context.ServiceProvider.GetService>().Value; + quartzOptions.StartSchedulerFactory = scheduler => Task.CompletedTask; + } + } } -} +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.BackgroundJobs.Quartz/Volo/Abp/BackgroundJobs/Quartz/QuartzBackgroundJobManageExtensions.cs b/framework/src/Volo.Abp.BackgroundJobs.Quartz/Volo/Abp/BackgroundJobs/Quartz/QuartzBackgroundJobManageExtensions.cs new file mode 100644 index 0000000000..3ba114b832 --- /dev/null +++ b/framework/src/Volo.Abp.BackgroundJobs.Quartz/Volo/Abp/BackgroundJobs/Quartz/QuartzBackgroundJobManageExtensions.cs @@ -0,0 +1,22 @@ +using System; +using System.Threading.Tasks; +using Quartz; + +namespace Volo.Abp.BackgroundJobs.Quartz +{ + public static class QuartzBackgroundJobManageExtensions + { + public static async Task EnqueueAsync(this IBackgroundJobManager backgroundJobManager, + TArgs args, int retryCount, int retryIntervalMillisecond, + BackgroundJobPriority priority = BackgroundJobPriority.Normal, TimeSpan? delay = null) + { + if (backgroundJobManager is QuartzBackgroundJobManager quartzBackgroundJobManager) + { + return await quartzBackgroundJobManager.ReEnqueueAsync(args, retryCount, retryIntervalMillisecond, + priority, delay); + } + + return null; + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.BackgroundJobs.Quartz/Volo/Abp/BackgroundJobs/Quartz/QuartzBackgroundJobManager.cs b/framework/src/Volo.Abp.BackgroundJobs.Quartz/Volo/Abp/BackgroundJobs/Quartz/QuartzBackgroundJobManager.cs index 2e7b8193b4..173d05e29b 100644 --- a/framework/src/Volo.Abp.BackgroundJobs.Quartz/Volo/Abp/BackgroundJobs/Quartz/QuartzBackgroundJobManager.cs +++ b/framework/src/Volo.Abp.BackgroundJobs.Quartz/Volo/Abp/BackgroundJobs/Quartz/QuartzBackgroundJobManager.cs @@ -1,5 +1,6 @@ using System; using System.Threading.Tasks; +using Microsoft.Extensions.Options; using Quartz; using Volo.Abp.DependencyInjection; @@ -7,20 +8,40 @@ namespace Volo.Abp.BackgroundJobs.Quartz { [Dependency(ReplaceServices = true)] public class QuartzBackgroundJobManager : IBackgroundJobManager, ITransientDependency - { - private readonly IScheduler _scheduler; - - public QuartzBackgroundJobManager(IScheduler scheduler) + { + public const string JobDataPrefix = "Abp"; + public const string RetryIndex = "RetryIndex"; + + protected IScheduler Scheduler { get; } + protected AbpBackgroundJobQuartzOptions Options { get; } + + + public QuartzBackgroundJobManager(IScheduler scheduler,IOptions options) { - _scheduler = scheduler; + Scheduler = scheduler; + Options = options.Value; } - public async Task EnqueueAsync(TArgs args, BackgroundJobPriority priority = BackgroundJobPriority.Normal, + public virtual async Task EnqueueAsync(TArgs args, BackgroundJobPriority priority = BackgroundJobPriority.Normal, TimeSpan? delay = null) { - var jobDetail = JobBuilder.Create>().SetJobData(new JobDataMap { { nameof(TArgs), args } }).Build(); + return await ReEnqueueAsync(args, Options.RetryCount, Options.RetryIntervalMillisecond, priority, delay); + } + + public virtual async Task ReEnqueueAsync(TArgs args, int retryCount, int retryIntervalMillisecond, + BackgroundJobPriority priority = BackgroundJobPriority.Normal, TimeSpan? delay = null) + { + var jobDataMap = new JobDataMap + { + {nameof(TArgs), args}, + {JobDataPrefix+ nameof(Options.RetryCount), retryCount}, + {JobDataPrefix+ nameof(Options.RetryIntervalMillisecond), retryIntervalMillisecond}, + {JobDataPrefix+ RetryIndex, 0} + }; + + var jobDetail = JobBuilder.Create>().RequestRecovery().SetJobData(jobDataMap).Build(); var trigger = !delay.HasValue ? TriggerBuilder.Create().StartNow().Build() : TriggerBuilder.Create().StartAt(new DateTimeOffset(DateTime.Now.Add(delay.Value))).Build(); - await _scheduler.ScheduleJob(jobDetail, trigger); + await Scheduler.ScheduleJob(jobDetail, trigger); return jobDetail.Key.ToString(); } } diff --git a/framework/src/Volo.Abp.BackgroundJobs.Quartz/Volo/Abp/BackgroundJobs/Quartz/QuartzJobExecutionAdapter.cs b/framework/src/Volo.Abp.BackgroundJobs.Quartz/Volo/Abp/BackgroundJobs/Quartz/QuartzJobExecutionAdapter.cs index 85a1ef736f..b6759b256e 100644 --- a/framework/src/Volo.Abp.BackgroundJobs.Quartz/Volo/Abp/BackgroundJobs/Quartz/QuartzJobExecutionAdapter.cs +++ b/framework/src/Volo.Abp.BackgroundJobs.Quartz/Volo/Abp/BackgroundJobs/Quartz/QuartzJobExecutionAdapter.cs @@ -1,6 +1,8 @@ using System; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; using Quartz; @@ -8,29 +10,50 @@ namespace Volo.Abp.BackgroundJobs.Quartz { public class QuartzJobExecutionAdapter : IJob { + public ILogger> Logger { get; set; } + protected AbpBackgroundJobOptions Options { get; } + protected AbpBackgroundJobQuartzOptions BackgroundJobQuartzOptions { get; } protected IServiceScopeFactory ServiceScopeFactory { get; } protected IBackgroundJobExecuter JobExecuter { get; } public QuartzJobExecutionAdapter( IOptions options, + IOptions backgroundJobQuartzOptions, IBackgroundJobExecuter jobExecuter, IServiceScopeFactory serviceScopeFactory) { JobExecuter = jobExecuter; ServiceScopeFactory = serviceScopeFactory; Options = options.Value; + BackgroundJobQuartzOptions = backgroundJobQuartzOptions.Value; + Logger = NullLogger>.Instance; } public async Task Execute(IJobExecutionContext context) { using (var scope = ServiceScopeFactory.CreateScope()) { - var args = (TArgs)context.JobDetail.JobDataMap.Get(nameof(TArgs)); + var args = (TArgs) context.JobDetail.JobDataMap.Get(nameof(TArgs)); var jobType = Options.GetJob(typeof(TArgs)).JobType; var jobContext = new JobExecutionContext(scope.ServiceProvider, jobType, args); - await JobExecuter.ExecuteAsync(jobContext); + try + { + await JobExecuter.ExecuteAsync(jobContext); + } + catch (Exception exception) + { + var jobExecutionException = new JobExecutionException(exception); + + var retryIndex = context.JobDetail.JobDataMap.GetIntValue(QuartzBackgroundJobManager.JobDataPrefix+ QuartzBackgroundJobManager.RetryIndex); + retryIndex++; + context.JobDetail.JobDataMap.Put(QuartzBackgroundJobManager.JobDataPrefix+ QuartzBackgroundJobManager.RetryIndex, retryIndex); + + await BackgroundJobQuartzOptions.RetryStrategy.Invoke(retryIndex, context, jobExecutionException); + + throw jobExecutionException; + } } } } -} +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/AbpBackgroundWorkerQuartzOptions.cs b/framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/AbpBackgroundWorkerQuartzOptions.cs new file mode 100644 index 0000000000..c4ca139b4e --- /dev/null +++ b/framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/AbpBackgroundWorkerQuartzOptions.cs @@ -0,0 +1,10 @@ +namespace Volo.Abp.BackgroundWorkers.Quartz +{ + public class AbpBackgroundWorkerQuartzOptions + { + /// + /// Default : true. + /// + public bool IsAutoRegisterEnabled { get; set; } = true; + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/AbpBackgroundWorkersQuartzModule.cs b/framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/AbpBackgroundWorkersQuartzModule.cs index 1f23b350aa..3c4f7131cb 100644 --- a/framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/AbpBackgroundWorkersQuartzModule.cs +++ b/framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/AbpBackgroundWorkersQuartzModule.cs @@ -1,5 +1,7 @@ -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; using Volo.Abp.Modularity; using Volo.Abp.Quartz; @@ -15,15 +17,30 @@ namespace Volo.Abp.BackgroundWorkers.Quartz { context.Services.AddConventionalRegistrar(new AbpQuartzConventionalRegistrar()); } + + public override void OnPreApplicationInitialization(ApplicationInitializationContext context) + { + var options = context.ServiceProvider.GetService>().Value; + if (!options.IsEnabled) + { + var quartzOptions = context.ServiceProvider.GetService>().Value; + quartzOptions.StartSchedulerFactory = scheduler => Task.CompletedTask; + } + } public override void OnApplicationInitialization(ApplicationInitializationContext context) { - var backgroundWorkerManager = context.ServiceProvider.GetService(); - var works = context.ServiceProvider.GetServices(); - - foreach (var work in works) + var options = context.ServiceProvider.GetService>().Value; + var quartzBackgroundWorkerOptions = context.ServiceProvider.GetService>().Value; + if (options.IsEnabled && quartzBackgroundWorkerOptions.IsAutoRegisterEnabled) { - backgroundWorkerManager.Add(work); + var backgroundWorkerManager = context.ServiceProvider.GetService(); + var works = context.ServiceProvider.GetServices().Where(x=>x.AutoRegister); + + foreach (var work in works) + { + backgroundWorkerManager.Add(work); + } } } } diff --git a/framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/IQuartzBackgroundWorker.cs b/framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/IQuartzBackgroundWorker.cs index ffc2117e6f..baf3fc1973 100644 --- a/framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/IQuartzBackgroundWorker.cs +++ b/framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/IQuartzBackgroundWorker.cs @@ -1,4 +1,6 @@ -using Quartz; +using System; +using System.Threading.Tasks; +using Quartz; namespace Volo.Abp.BackgroundWorkers.Quartz { @@ -7,5 +9,9 @@ namespace Volo.Abp.BackgroundWorkers.Quartz ITrigger Trigger { get; set; } IJobDetail JobDetail { get; set; } + + bool AutoRegister { get; set; } + + Func ScheduleJob { get; set; } } } diff --git a/framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/QuartzBackgroundWorkerBase.cs b/framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/QuartzBackgroundWorkerBase.cs index e468ac80f5..307e6b6676 100644 --- a/framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/QuartzBackgroundWorkerBase.cs +++ b/framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/QuartzBackgroundWorkerBase.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System; +using System.Threading.Tasks; using Quartz; namespace Volo.Abp.BackgroundWorkers.Quartz @@ -8,6 +9,10 @@ namespace Volo.Abp.BackgroundWorkers.Quartz public ITrigger Trigger { get; set; } public IJobDetail JobDetail { get; set; } + + public bool AutoRegister { get; set; } = true; + + public Func ScheduleJob { get; set; } = null; public abstract Task Execute(IJobExecutionContext context); } diff --git a/framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/QuartzBackgroundWorkerManager.cs b/framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/QuartzBackgroundWorkerManager.cs index 46568a5a11..35359b1d27 100644 --- a/framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/QuartzBackgroundWorkerManager.cs +++ b/framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/QuartzBackgroundWorkerManager.cs @@ -16,12 +16,12 @@ namespace Volo.Abp.BackgroundWorkers.Quartz _scheduler = scheduler; } - public async Task StartAsync(CancellationToken cancellationToken = default) + public virtual async Task StartAsync(CancellationToken cancellationToken = default) { await _scheduler.ResumeAll(cancellationToken); } - public async Task StopAsync(CancellationToken cancellationToken = default) + public virtual async Task StopAsync(CancellationToken cancellationToken = default) { if (!_scheduler.IsShutdown) { @@ -29,15 +29,41 @@ namespace Volo.Abp.BackgroundWorkers.Quartz } } - public void Add(IBackgroundWorker worker) + public virtual void Add(IBackgroundWorker worker) + { + AsyncHelper.RunSync(() => ReScheduleJobAsync(worker)); + } + + protected virtual async Task ReScheduleJobAsync(IBackgroundWorker worker) { if (worker is IQuartzBackgroundWorker quartzWork) { Check.NotNull(quartzWork.Trigger, nameof(quartzWork.Trigger)); Check.NotNull(quartzWork.JobDetail, nameof(quartzWork.JobDetail)); - AsyncHelper.RunSync(() => _scheduler.ScheduleJob(quartzWork.JobDetail, quartzWork.Trigger)); + if (quartzWork.ScheduleJob != null) + { + await quartzWork.ScheduleJob.Invoke(_scheduler); + } + else + { + await DefaultScheduleJobAsync(quartzWork); + } + } + } + + protected virtual async Task DefaultScheduleJobAsync(IQuartzBackgroundWorker quartzWork) + { + if (await _scheduler.CheckExists(quartzWork.JobDetail.Key)) + { + await _scheduler.AddJob(quartzWork.JobDetail, true, true); + await _scheduler.ResumeJob(quartzWork.JobDetail.Key); + await _scheduler.RescheduleJob(quartzWork.Trigger.Key, quartzWork.Trigger); + } + else + { + await _scheduler.ScheduleJob(quartzWork.JobDetail, quartzWork.Trigger); } } } -} +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Quartz/Volo/Abp/Quartz/AbpQuartzModule.cs b/framework/src/Volo.Abp.Quartz/Volo/Abp/Quartz/AbpQuartzModule.cs index 9112f2baaf..3a2413a9b8 100644 --- a/framework/src/Volo.Abp.Quartz/Volo/Abp/Quartz/AbpQuartzModule.cs +++ b/framework/src/Volo.Abp.Quartz/Volo/Abp/Quartz/AbpQuartzModule.cs @@ -14,32 +14,33 @@ namespace Volo.Abp.Quartz public override void ConfigureServices(ServiceConfigurationContext context) { - var options = context.Services.ExecutePreConfiguredActions(); + var options = context.Services.ExecutePreConfiguredActions(); context.Services.AddSingleton(AsyncHelper.RunSync(() => new StdSchedulerFactory(options.Properties).GetScheduler())); context.Services.AddSingleton(typeof(IJobFactory), typeof(AbpQuartzJobFactory)); + + Configure(quartzOptions => + { + quartzOptions.Properties = options.Properties; + quartzOptions.StartDelay = options.StartDelay; + }); } public override void OnApplicationInitialization(ApplicationInitializationContext context) { - var options = context.ServiceProvider.GetRequiredService>().Value; - + var options = context.ServiceProvider.GetRequiredService>().Value; + _scheduler = context.ServiceProvider.GetService(); _scheduler.JobFactory = context.ServiceProvider.GetService(); - - if (options.StartDelay.Ticks > 0) - { - AsyncHelper.RunSync(() => _scheduler.StartDelayed(options.StartDelay)); - } - else - { - AsyncHelper.RunSync(() => _scheduler.Start()); - } + + AsyncHelper.RunSync(() => options.StartSchedulerFactory.Invoke(_scheduler)); } public override void OnApplicationShutdown(ApplicationShutdownContext context) { - //TODO: ABP may provide two methods for application shutdown: OnPreApplicationShutdown & OnApplicationShutdown - AsyncHelper.RunSync(() => _scheduler.Shutdown()); + if (_scheduler.IsStarted) + { + AsyncHelper.RunSync(() => _scheduler.Shutdown()); + } } } -} +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Quartz/Volo/Abp/Quartz/AbpQuartzOptions.cs b/framework/src/Volo.Abp.Quartz/Volo/Abp/Quartz/AbpQuartzOptions.cs new file mode 100644 index 0000000000..9998676042 --- /dev/null +++ b/framework/src/Volo.Abp.Quartz/Volo/Abp/Quartz/AbpQuartzOptions.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Specialized; +using System.Threading.Tasks; +using JetBrains.Annotations; +using Quartz; + +namespace Volo.Abp.Quartz +{ + public class AbpQuartzOptions + { + /// + /// The quartz configuration. Available properties can be found within Quartz.Impl.StdSchedulerFactory. + /// + public NameValueCollection Properties { get; set; } + + /// + /// How long Quartz should wait before starting. Default: 0. + /// + public TimeSpan StartDelay { get; set; } + + [NotNull] + public Func StartSchedulerFactory + { + get => _startSchedulerFactory; + set => _startSchedulerFactory = Check.NotNull(value, nameof(value)); + } + private Func _startSchedulerFactory; + + public AbpQuartzOptions() + { + Properties = new NameValueCollection(); + StartDelay = new TimeSpan(0); + _startSchedulerFactory = StartSchedulerAsync; + } + + private async Task StartSchedulerAsync(IScheduler scheduler) + { + if (StartDelay.Ticks > 0) + { + await scheduler.StartDelayed(StartDelay); + } + else + { + await scheduler.Start(); + } + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.Quartz/Volo/Abp/Quartz/AbpQuartzPreOptions.cs b/framework/src/Volo.Abp.Quartz/Volo/Abp/Quartz/AbpQuartzPreOptions.cs deleted file mode 100644 index 9e48744d96..0000000000 --- a/framework/src/Volo.Abp.Quartz/Volo/Abp/Quartz/AbpQuartzPreOptions.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.Collections.Specialized; - -namespace Volo.Abp.Quartz -{ - public class AbpQuartzPreOptions - { - /// - /// The quartz configuration. Available properties can be found within Quartz.Impl.StdSchedulerFactory. - /// - public NameValueCollection Properties { get; set; } - /// - /// How long Quartz should wait before starting. Default: 0. - /// - public TimeSpan StartDelay { get; set; } - - public AbpQuartzPreOptions() - { - Properties = new NameValueCollection(); - StartDelay = new TimeSpan(0); - } - } -}