From 902601c016089a5b7062be8afe37f569c14f81b8 Mon Sep 17 00:00:00 2001 From: maliming Date: Sat, 22 Feb 2025 17:59:21 +0800 Subject: [PATCH] Add `ApplicationName` property to background job to isolation jobs. --- Directory.Packages.props | 1 + .../Hangfire/HangfireBackgroundJobManager.cs | 19 +++--- .../AbpBackgroundJobWorkerOptions.cs | 5 ++ .../Abp/BackgroundJobs/BackgroundJobInfo.cs | 5 ++ .../Abp/BackgroundJobs/BackgroundJobWorker.cs | 2 +- .../DefaultBackgroundJobManager.cs | 8 ++- .../Abp/BackgroundJobs/IBackgroundJobStore.cs | 5 +- .../InMemoryBackgroundJobStore.cs | 3 +- .../Hangfire/HangfireBackgroundWorkerBase.cs | 2 +- .../HangfireBackgroundWorkerManager.cs | 23 ++++--- .../Volo/Abp/Hangfire/AbpHangfireModule.cs | 4 ++ .../Volo/Abp/Hangfire/AbpHangfireOptions.cs | 12 ++++ .../AbpHangfireOptionsConfiguration.cs | 65 +++++++++++++++++++ .../BackgroundJobRecordConsts.cs | 5 ++ .../Abp/BackgroundJobs/BackgroundJobRecord.cs | 5 ++ .../Abp/BackgroundJobs/BackgroundJobStore.cs | 4 +- .../IBackgroundJobRepository.cs | 3 +- ...undJobsDbContextModelCreatingExtensions.cs | 1 + .../EfCoreBackgroundJobRepository.cs | 10 +-- .../MongoDB/MongoBackgroundJobRepository.cs | 10 +-- .../BackgroundJobRepository_Tests.cs | 9 ++- .../BackgroundJobsTestDataBuilder.cs | 3 + 22 files changed, 163 insertions(+), 41 deletions(-) create mode 100644 framework/src/Volo.Abp.HangFire/Volo/Abp/Hangfire/AbpHangfireOptionsConfiguration.cs diff --git a/Directory.Packages.props b/Directory.Packages.props index 7a0067896d..2c1f52a9dc 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -77,6 +77,7 @@ + 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 a94426adad..0a47399e49 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 @@ -5,17 +5,20 @@ using Hangfire; using Hangfire.States; using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; +using Volo.Abp.Hangfire; namespace Volo.Abp.BackgroundJobs.Hangfire; [Dependency(ReplaceServices = true)] public class HangfireBackgroundJobManager : IBackgroundJobManager, ITransientDependency { - protected AbpBackgroundJobOptions Options { get; } + protected IOptions BackgroundJobOptions { get; } + protected IOptions HangfireOptions { get; } - public HangfireBackgroundJobManager(IOptions options) + public HangfireBackgroundJobManager(IOptions backgroundJobOptions, IOptions hangfireOptions) { - Options = options.Value; + BackgroundJobOptions = backgroundJobOptions; + HangfireOptions = hangfireOptions; } public virtual Task EnqueueAsync(TArgs args, BackgroundJobPriority priority = BackgroundJobPriority.Normal, @@ -33,13 +36,7 @@ public class HangfireBackgroundJobManager : IBackgroundJobManager, ITransientDep protected virtual string GetQueueName(Type argsType) { - var queueName = EnqueuedState.DefaultQueue; - var queueAttribute = Options.GetJob(argsType).JobType.GetCustomAttribute(); - if (queueAttribute != null) - { - queueName = queueAttribute.Queue; - } - - return queueName; + var queueAttribute = BackgroundJobOptions.Value.GetJob(argsType).JobType.GetCustomAttribute(); + return queueAttribute != null ? HangfireOptions.Value.DefaultQueuePrefix + queueAttribute.Queue : HangfireOptions.Value.DefaultQueue; } } diff --git a/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/AbpBackgroundJobWorkerOptions.cs b/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/AbpBackgroundJobWorkerOptions.cs index 3bc31e7a39..b339508028 100644 --- a/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/AbpBackgroundJobWorkerOptions.cs +++ b/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/AbpBackgroundJobWorkerOptions.cs @@ -2,6 +2,11 @@ public class AbpBackgroundJobWorkerOptions { + /// + /// Application name. + /// + public string? ApplicationName { get; set; } + /// /// Interval between polling jobs from . /// Default value: 5000 (5 seconds). diff --git a/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/BackgroundJobInfo.cs b/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/BackgroundJobInfo.cs index 0d5441a4bc..4a9cec922c 100644 --- a/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/BackgroundJobInfo.cs +++ b/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/BackgroundJobInfo.cs @@ -9,6 +9,11 @@ public class BackgroundJobInfo { public Guid Id { get; set; } + /// + /// Application name. + /// + public virtual string? ApplicationName { get; set; } + /// /// Name of the job. /// diff --git a/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/BackgroundJobWorker.cs b/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/BackgroundJobWorker.cs index 4313350098..a015e32d66 100644 --- a/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/BackgroundJobWorker.cs +++ b/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/BackgroundJobWorker.cs @@ -43,7 +43,7 @@ public class BackgroundJobWorker : AsyncPeriodicBackgroundWorkerBase, IBackgroun { var store = workerContext.ServiceProvider.GetRequiredService(); - var waitingJobs = await store.GetWaitingJobsAsync(WorkerOptions.MaxJobFetchCount); + var waitingJobs = await store.GetWaitingJobsAsync(WorkerOptions.ApplicationName, WorkerOptions.MaxJobFetchCount); if (!waitingJobs.Any()) { diff --git a/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/DefaultBackgroundJobManager.cs b/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/DefaultBackgroundJobManager.cs index 7218776cfe..68851c5043 100644 --- a/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/DefaultBackgroundJobManager.cs +++ b/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/DefaultBackgroundJobManager.cs @@ -1,5 +1,7 @@ using System; using System.Threading.Tasks; +using Microsoft.Extensions.Options; +using Volo.Abp.BackgroundWorkers; using Volo.Abp.DependencyInjection; using Volo.Abp.Guids; using Volo.Abp.Timing; @@ -16,16 +18,19 @@ public class DefaultBackgroundJobManager : IBackgroundJobManager, ITransientDepe protected IBackgroundJobSerializer Serializer { get; } protected IGuidGenerator GuidGenerator { get; } protected IBackgroundJobStore Store { get; } + protected IOptions BackgroundJobWorkerOptions { get; } public DefaultBackgroundJobManager( IClock clock, IBackgroundJobSerializer serializer, IBackgroundJobStore store, - IGuidGenerator guidGenerator) + IGuidGenerator guidGenerator, + IOptions backgroundJobWorkerOptions) { Clock = clock; Serializer = serializer; GuidGenerator = guidGenerator; + BackgroundJobWorkerOptions = backgroundJobWorkerOptions; Store = store; } @@ -41,6 +46,7 @@ public class DefaultBackgroundJobManager : IBackgroundJobManager, ITransientDepe var jobInfo = new BackgroundJobInfo { Id = GuidGenerator.Create(), + ApplicationName = BackgroundJobWorkerOptions.Value.ApplicationName, JobName = jobName, JobArgs = Serializer.Serialize(args), Priority = priority, diff --git a/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/IBackgroundJobStore.cs b/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/IBackgroundJobStore.cs index 4a3a8d1ac0..7fcf8cc5b6 100644 --- a/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/IBackgroundJobStore.cs +++ b/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/IBackgroundJobStore.cs @@ -24,12 +24,13 @@ public interface IBackgroundJobStore /// /// Gets waiting jobs. It should get jobs based on these: - /// Conditions: !IsAbandoned And NextTryTime <= Clock.Now. + /// Conditions: ApplicationName is applicationName And !IsAbandoned And NextTryTime <= Clock.Now. /// Order by: Priority DESC, TryCount ASC, NextTryTime ASC. /// Maximum result: . /// + /// Application name. /// Maximum result count. - Task> GetWaitingJobsAsync(int maxResultCount); + Task> GetWaitingJobsAsync(string? applicationName, int maxResultCount); /// /// Deletes a job. diff --git a/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/InMemoryBackgroundJobStore.cs b/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/InMemoryBackgroundJobStore.cs index 7abbc188ce..85916e8c37 100644 --- a/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/InMemoryBackgroundJobStore.cs +++ b/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/InMemoryBackgroundJobStore.cs @@ -35,9 +35,10 @@ public class InMemoryBackgroundJobStore : IBackgroundJobStore, ISingletonDepende return Task.CompletedTask; } - public virtual Task> GetWaitingJobsAsync(int maxResultCount) + public virtual Task> GetWaitingJobsAsync(string? applicationName, int maxResultCount) { var waitingJobs = _jobs.Values + .Where(t => t.ApplicationName == applicationName) .Where(t => !t.IsAbandoned && t.NextTryTime <= Clock.Now) .OrderByDescending(t => t.Priority) .ThenBy(t => t.TryCount) diff --git a/framework/src/Volo.Abp.BackgroundWorkers.Hangfire/Volo/Abp/BackgroundWorkers/Hangfire/HangfireBackgroundWorkerBase.cs b/framework/src/Volo.Abp.BackgroundWorkers.Hangfire/Volo/Abp/BackgroundWorkers/Hangfire/HangfireBackgroundWorkerBase.cs index 0c1a5f3d26..0c9ba67603 100644 --- a/framework/src/Volo.Abp.BackgroundWorkers.Hangfire/Volo/Abp/BackgroundWorkers/Hangfire/HangfireBackgroundWorkerBase.cs +++ b/framework/src/Volo.Abp.BackgroundWorkers.Hangfire/Volo/Abp/BackgroundWorkers/Hangfire/HangfireBackgroundWorkerBase.cs @@ -13,7 +13,7 @@ public abstract class HangfireBackgroundWorkerBase : BackgroundWorkerBase, IHang public TimeZoneInfo? TimeZone { get; set; } = TimeZoneInfo.Utc; - public string Queue { get; set; } = EnqueuedState.DefaultQueue; + public string Queue { get; set; } = default!; public abstract Task DoWorkAsync(CancellationToken cancellationToken = default); } diff --git a/framework/src/Volo.Abp.BackgroundWorkers.Hangfire/Volo/Abp/BackgroundWorkers/Hangfire/HangfireBackgroundWorkerManager.cs b/framework/src/Volo.Abp.BackgroundWorkers.Hangfire/Volo/Abp/BackgroundWorkers/Hangfire/HangfireBackgroundWorkerManager.cs index 9c79056ec2..1ed3561cac 100644 --- a/framework/src/Volo.Abp.BackgroundWorkers.Hangfire/Volo/Abp/BackgroundWorkers/Hangfire/HangfireBackgroundWorkerManager.cs +++ b/framework/src/Volo.Abp.BackgroundWorkers.Hangfire/Volo/Abp/BackgroundWorkers/Hangfire/HangfireBackgroundWorkerManager.cs @@ -4,6 +4,7 @@ using System.Threading; using System.Threading.Tasks; using Hangfire; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; using Volo.Abp.DynamicProxy; using Volo.Abp.Hangfire; @@ -30,15 +31,19 @@ public class HangfireBackgroundWorkerManager : BackgroundWorkerManager, ISinglet public async override Task AddAsync(IBackgroundWorker worker, CancellationToken cancellationToken = default) { + var abpHangfireOptions = ServiceProvider.GetRequiredService>().Value; + var defaultQueuePrefix = abpHangfireOptions.DefaultQueuePrefix; + var defaultQueue = abpHangfireOptions.DefaultQueue; + switch (worker) { case IHangfireBackgroundWorker hangfireBackgroundWorker: { var unProxyWorker = ProxyHelper.UnProxy(hangfireBackgroundWorker); - + RecurringJob.AddOrUpdate( hangfireBackgroundWorker.RecurringJobId, - hangfireBackgroundWorker.Queue, + hangfireBackgroundWorker.Queue.IsNullOrWhiteSpace() ? defaultQueue : defaultQueuePrefix + hangfireBackgroundWorker.Queue, () => ((IHangfireBackgroundWorker)unProxyWorker).DoWorkAsync(cancellationToken), hangfireBackgroundWorker.CronExpression, new RecurringJobOptions @@ -57,24 +62,24 @@ public class HangfireBackgroundWorkerManager : BackgroundWorkerManager, ISinglet { return; } - + var adapterType = typeof(HangfirePeriodicBackgroundWorkerAdapter<>).MakeGenericType(ProxyHelper.GetUnProxiedType(worker)); var workerAdapter = (Activator.CreateInstance(adapterType) as IHangfireBackgroundWorker)!; if (workerAdapter.RecurringJobId.IsNullOrWhiteSpace()) { - RecurringJob.AddOrUpdate( + RecurringJob.AddOrUpdate( () => workerAdapter.DoWorkAsync(cancellationToken), GetCron(period.Value), workerAdapter.TimeZone , - workerAdapter.Queue); + workerAdapter.Queue.IsNullOrWhiteSpace() ? defaultQueue : defaultQueuePrefix + workerAdapter.Queue); } else { - + RecurringJob.AddOrUpdate( workerAdapter.RecurringJobId, - workerAdapter.Queue, + workerAdapter.Queue.IsNullOrWhiteSpace() ? defaultQueue : defaultQueuePrefix + workerAdapter.Queue, () => workerAdapter.DoWorkAsync(cancellationToken), GetCron(period.Value), new RecurringJobOptions @@ -82,7 +87,7 @@ public class HangfireBackgroundWorkerManager : BackgroundWorkerManager, ISinglet TimeZone = workerAdapter.TimeZone }); } - + break; } @@ -121,4 +126,4 @@ public class HangfireBackgroundWorkerManager : BackgroundWorkerManager, ISinglet return cron; } -} \ No newline at end of file +} diff --git a/framework/src/Volo.Abp.HangFire/Volo/Abp/Hangfire/AbpHangfireModule.cs b/framework/src/Volo.Abp.HangFire/Volo/Abp/Hangfire/AbpHangfireModule.cs index 6c34b86904..2b75155e7b 100644 --- a/framework/src/Volo.Abp.HangFire/Volo/Abp/Hangfire/AbpHangfireModule.cs +++ b/framework/src/Volo.Abp.HangFire/Volo/Abp/Hangfire/AbpHangfireModule.cs @@ -1,5 +1,6 @@ using Hangfire; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Options; using Volo.Abp.Authorization; using Volo.Abp.Modularity; @@ -24,7 +25,10 @@ public class AbpHangfireModule : AbpModule var options = serviceProvider.GetRequiredService>().Value; return new AbpHangfireBackgroundJobServer(options.BackgroundJobServerFactory.Invoke(serviceProvider)); }); + + context.Services.TryAddEnumerable(ServiceDescriptor.Singleton, AbpHangfireOptionsConfiguration>()); } + public override void OnApplicationInitialization(ApplicationInitializationContext context) { _backgroundJobServer = context.ServiceProvider.GetRequiredService(); diff --git a/framework/src/Volo.Abp.HangFire/Volo/Abp/Hangfire/AbpHangfireOptions.cs b/framework/src/Volo.Abp.HangFire/Volo/Abp/Hangfire/AbpHangfireOptions.cs index 98c45348c7..8ed90d17c7 100644 --- a/framework/src/Volo.Abp.HangFire/Volo/Abp/Hangfire/AbpHangfireOptions.cs +++ b/framework/src/Volo.Abp.HangFire/Volo/Abp/Hangfire/AbpHangfireOptions.cs @@ -12,6 +12,18 @@ namespace Volo.Abp.Hangfire; public class AbpHangfireOptions { + /// + /// This value is used to add prefix to all of the queues. Default is empty. + /// + public string DefaultQueuePrefix { get; set; } = string.Empty; + + /// + /// Hangfire queue name max length, default is 50. + /// + public int MaxQueueNameLength { get; set; } = 50; + + public string DefaultQueue { get; set; } = EnqueuedState.DefaultQueue; + public BackgroundJobServerOptions? ServerOptions { get; set; } public IEnumerable? AdditionalProcesses { get; set; } diff --git a/framework/src/Volo.Abp.HangFire/Volo/Abp/Hangfire/AbpHangfireOptionsConfiguration.cs b/framework/src/Volo.Abp.HangFire/Volo/Abp/Hangfire/AbpHangfireOptionsConfiguration.cs new file mode 100644 index 0000000000..1fb5dcd8dc --- /dev/null +++ b/framework/src/Volo.Abp.HangFire/Volo/Abp/Hangfire/AbpHangfireOptionsConfiguration.cs @@ -0,0 +1,65 @@ +using System; +using System.Linq; +using System.Text.RegularExpressions; +using Hangfire; +using Hangfire.States; +using Microsoft.Extensions.Options; + +namespace Volo.Abp.Hangfire; + +public class AbpHangfireOptionsConfiguration : IPostConfigureOptions +{ + public void PostConfigure(string? name, AbpHangfireOptions options) + { + if (options.DefaultQueuePrefix.IsNullOrWhiteSpace()) + { + return;; + } + + // The Queue name argument must consist of lowercase letters, digits, underscore, and dash characters only. + var queuesPrefix = Regex.Replace(options.DefaultQueuePrefix.ToLower().Replace(".", "_"), "[^a-z0-9_-]", ""); + if (queuesPrefix.IsNullOrWhiteSpace()) + { + throw new AbpException($"The QueuesPrefix({options.DefaultQueuePrefix}) is not valid, it must consist of lowercase letters, digits, underscore, and dash characters only."); + } + + options.DefaultQueuePrefix = queuesPrefix.EnsureEndsWith('_'); + + if (options.ServerOptions == null) + { + var queue = $"{options.DefaultQueuePrefix}{EnqueuedState.DefaultQueue}"; + if (queue.Length > options.MaxQueueNameLength) + { + throw new AbpException($"The maximum length of the Hangfire queue name({queue}) is {options.MaxQueueNameLength}, Please configure the AbpHangfireOptions.DefaultQueuePrefix manually."); + } + options.ServerOptions = new BackgroundJobServerOptions + { + Queues = new[] { queue } + }; + options.DefaultQueue = queue; + } + else + { + var queues = options.ServerOptions.Queues; + for (var i = 0; i < queues.Length; i++) + { + var queue = $"{options.DefaultQueuePrefix}{queues[i]}"; + if (queue.Length > options.MaxQueueNameLength) + { + throw new AbpException($"The maximum length of the Hangfire queue name({queue}) is {options.MaxQueueNameLength}, Please configure the AbpHangfireOptions.DefaultQueuePrefix manually."); + } + queues[i] = queue; + } + var defaultQueue = queues.FirstOrDefault(q => q.EndsWith(EnqueuedState.DefaultQueue)); + if (defaultQueue.IsNullOrWhiteSpace()) + { + defaultQueue = queues.FirstOrDefault(); + if (defaultQueue.IsNullOrWhiteSpace()) + { + throw new AbpException("There is no queue defined in the Hangfire configuration!"); + } + } + options.DefaultQueue = defaultQueue; + } + } +} diff --git a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain.Shared/Volo/Abp/BackgroundJobs/BackgroundJobRecordConsts.cs b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain.Shared/Volo/Abp/BackgroundJobs/BackgroundJobRecordConsts.cs index 4369bfcece..7cf4e651fe 100644 --- a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain.Shared/Volo/Abp/BackgroundJobs/BackgroundJobRecordConsts.cs +++ b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain.Shared/Volo/Abp/BackgroundJobs/BackgroundJobRecordConsts.cs @@ -2,6 +2,11 @@ public static class BackgroundJobRecordConsts { + /// + /// Default value: 96 + /// + public static int MaxApplicationNameLength { get; set; } = 96; + /// /// Default value: 128 /// diff --git a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/BackgroundJobRecord.cs b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/BackgroundJobRecord.cs index 66714af6d6..c01f933781 100644 --- a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/BackgroundJobRecord.cs +++ b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/BackgroundJobRecord.cs @@ -6,6 +6,11 @@ namespace Volo.Abp.BackgroundJobs; public class BackgroundJobRecord : AggregateRoot, IHasCreationTime { + /// + /// Application name that scheduled this job. + /// + public virtual string ApplicationName { get; set; } + /// /// Type of the job. /// It's AssemblyQualifiedName of job type. diff --git a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/BackgroundJobStore.cs b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/BackgroundJobStore.cs index e29948cc95..c7dbd6fbef 100644 --- a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/BackgroundJobStore.cs +++ b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/BackgroundJobStore.cs @@ -34,10 +34,10 @@ public class BackgroundJobStore : IBackgroundJobStore, ITransientDependency ); } - public virtual async Task> GetWaitingJobsAsync(int maxResultCount) + public virtual async Task> GetWaitingJobsAsync(string applicationName, int maxResultCount) { return ObjectMapper.Map, List>( - await BackgroundJobRepository.GetWaitingListAsync(maxResultCount) + await BackgroundJobRepository.GetWaitingListAsync(applicationName, maxResultCount) ); } diff --git a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/IBackgroundJobRepository.cs b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/IBackgroundJobRepository.cs index b3c552c974..7e189df5c8 100644 --- a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/IBackgroundJobRepository.cs +++ b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.Domain/Volo/Abp/BackgroundJobs/IBackgroundJobRepository.cs @@ -2,11 +2,12 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using JetBrains.Annotations; using Volo.Abp.Domain.Repositories; namespace Volo.Abp.BackgroundJobs; public interface IBackgroundJobRepository : IBasicRepository { - Task> GetWaitingListAsync(int maxResultCount, CancellationToken cancellationToken = default); + Task> GetWaitingListAsync([CanBeNull] string applicationName, int maxResultCount, CancellationToken cancellationToken = default); } diff --git a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo/Abp/BackgroundJobs/EntityFrameworkCore/BackgroundJobsDbContextModelCreatingExtensions.cs b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo/Abp/BackgroundJobs/EntityFrameworkCore/BackgroundJobsDbContextModelCreatingExtensions.cs index 5b51c8809d..53a2c53843 100644 --- a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo/Abp/BackgroundJobs/EntityFrameworkCore/BackgroundJobsDbContextModelCreatingExtensions.cs +++ b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo/Abp/BackgroundJobs/EntityFrameworkCore/BackgroundJobsDbContextModelCreatingExtensions.cs @@ -22,6 +22,7 @@ public static class BackgroundJobsDbContextModelCreatingExtensions b.ConfigureByConvention(); + b.Property(x => x.ApplicationName).IsRequired(false).HasMaxLength(BackgroundJobRecordConsts.MaxApplicationNameLength); b.Property(x => x.JobName).IsRequired().HasMaxLength(BackgroundJobRecordConsts.MaxJobNameLength); b.Property(x => x.JobArgs).IsRequired().HasMaxLength(BackgroundJobRecordConsts.MaxJobArgsLength); b.Property(x => x.TryCount).HasDefaultValue(0); diff --git a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo/Abp/BackgroundJobs/EntityFrameworkCore/EfCoreBackgroundJobRepository.cs b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo/Abp/BackgroundJobs/EntityFrameworkCore/EfCoreBackgroundJobRepository.cs index a2be3c6e1e..a81de3cdfb 100644 --- a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo/Abp/BackgroundJobs/EntityFrameworkCore/EfCoreBackgroundJobRepository.cs +++ b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.EntityFrameworkCore/Volo/Abp/BackgroundJobs/EntityFrameworkCore/EfCoreBackgroundJobRepository.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using JetBrains.Annotations; using Microsoft.EntityFrameworkCore; using Volo.Abp.Domain.Repositories.EntityFrameworkCore; using Volo.Abp.EntityFrameworkCore; @@ -22,17 +23,16 @@ public class EfCoreBackgroundJobRepository : EfCoreRepository> GetWaitingListAsync( - int maxResultCount, - CancellationToken cancellationToken = default) + public virtual async Task> GetWaitingListAsync([CanBeNull] string applicationName, int maxResultCount, CancellationToken cancellationToken = default) { - return await (await GetWaitingListQueryAsync(maxResultCount)).ToListAsync(GetCancellationToken(cancellationToken)); + return await (await GetWaitingListQueryAsync(applicationName, maxResultCount)).ToListAsync(GetCancellationToken(cancellationToken)); } - protected virtual async Task> GetWaitingListQueryAsync(int maxResultCount) + protected virtual async Task> GetWaitingListQueryAsync([CanBeNull] string applicationName, int maxResultCount) { var now = Clock.Now; return (await GetDbSetAsync()) + .Where(t => t.ApplicationName == applicationName) .Where(t => !t.IsAbandoned && t.NextTryTime <= now) .OrderByDescending(t => t.Priority) .ThenBy(t => t.TryCount) diff --git a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.MongoDB/Volo/Abp/BackgroundJobs/MongoDB/MongoBackgroundJobRepository.cs b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.MongoDB/Volo/Abp/BackgroundJobs/MongoDB/MongoBackgroundJobRepository.cs index a3f46643fe..71a5680524 100644 --- a/modules/background-jobs/src/Volo.Abp.BackgroundJobs.MongoDB/Volo/Abp/BackgroundJobs/MongoDB/MongoBackgroundJobRepository.cs +++ b/modules/background-jobs/src/Volo.Abp.BackgroundJobs.MongoDB/Volo/Abp/BackgroundJobs/MongoDB/MongoBackgroundJobRepository.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using System.Linq; +using JetBrains.Annotations; using MongoDB.Driver; using MongoDB.Driver.Linq; using Volo.Abp.Domain.Repositories.MongoDB; @@ -23,17 +24,16 @@ public class MongoBackgroundJobRepository : MongoDbRepository> GetWaitingListAsync( - int maxResultCount, - CancellationToken cancellationToken = default) + public virtual async Task> GetWaitingListAsync([CanBeNull] string applicationName, int maxResultCount, CancellationToken cancellationToken = default) { - return await (await GetWaitingListQuery(maxResultCount)).ToListAsync(GetCancellationToken(cancellationToken)); + return await (await GetWaitingListQuery(applicationName, maxResultCount, cancellationToken)).ToListAsync(GetCancellationToken(cancellationToken)); } - protected virtual async Task> GetWaitingListQuery(int maxResultCount, CancellationToken cancellationToken = default) + protected virtual async Task> GetWaitingListQuery([CanBeNull] string applicationName, int maxResultCount, CancellationToken cancellationToken = default) { var now = Clock.Now; return (await GetQueryableAsync(cancellationToken)) + .Where(t => t.ApplicationName == applicationName) .Where(t => !t.IsAbandoned && t.NextTryTime <= now) .OrderByDescending(t => t.Priority) .ThenBy(t => t.TryCount) diff --git a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.TestBase/Volo/Abp/BackgroundJobs/BackgroundJobRepository_Tests.cs b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.TestBase/Volo/Abp/BackgroundJobs/BackgroundJobRepository_Tests.cs index 02e4fa9d60..c62cb43309 100644 --- a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.TestBase/Volo/Abp/BackgroundJobs/BackgroundJobRepository_Tests.cs +++ b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.TestBase/Volo/Abp/BackgroundJobs/BackgroundJobRepository_Tests.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System.Linq; +using System.Threading.Tasks; using Shouldly; using Volo.Abp.Modularity; using Volo.Abp.Timing; @@ -23,12 +24,16 @@ public abstract class BackgroundJobRepository_Tests : Background [InlineData(5)] public async Task GetWaitingListAsync(int maxResultCount) { - var backgroundJobs = await _backgroundJobRepository.GetWaitingListAsync(maxResultCount); + var backgroundJobs = await _backgroundJobRepository.GetWaitingListAsync("App1", maxResultCount); backgroundJobs.Count.ShouldBeGreaterThan(0); backgroundJobs.Count.ShouldBeLessThanOrEqualTo(maxResultCount); backgroundJobs.ForEach(j => j.IsAbandoned.ShouldBeFalse()); backgroundJobs.ForEach(j => j.NextTryTime.ShouldBeLessThanOrEqualTo(_clock.Now.AddSeconds(1))); //1 second tolerance + + backgroundJobs.All(j => j.ApplicationName == "App1").ShouldBeTrue(); + backgroundJobs.Any(j => j.ApplicationName == "App2").ShouldBeFalse(); + backgroundJobs.Any(j => j.ApplicationName == null).ShouldBeFalse(); } } diff --git a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.TestBase/Volo/Abp/BackgroundJobs/BackgroundJobsTestDataBuilder.cs b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.TestBase/Volo/Abp/BackgroundJobs/BackgroundJobsTestDataBuilder.cs index 079a0ab3ea..f6f4c37e12 100644 --- a/modules/background-jobs/test/Volo.Abp.BackgroundJobs.TestBase/Volo/Abp/BackgroundJobs/BackgroundJobsTestDataBuilder.cs +++ b/modules/background-jobs/test/Volo.Abp.BackgroundJobs.TestBase/Volo/Abp/BackgroundJobs/BackgroundJobsTestDataBuilder.cs @@ -26,6 +26,7 @@ public class BackgroundJobsTestDataBuilder : ITransientDependency await _backgroundJobRepository.InsertAsync( new BackgroundJobRecord(_testData.JobId1) { + ApplicationName = "App1", JobName = "TestJobName", JobArgs = "{ value: 1 }", NextTryTime = _clock.Now.Subtract(TimeSpan.FromMinutes(1)), @@ -40,6 +41,7 @@ public class BackgroundJobsTestDataBuilder : ITransientDependency await _backgroundJobRepository.InsertAsync( new BackgroundJobRecord(_testData.JobId2) { + ApplicationName = "App2", JobName = "TestJobName", JobArgs = "{ value: 2 }", NextTryTime = _clock.Now.AddMinutes(42), @@ -54,6 +56,7 @@ public class BackgroundJobsTestDataBuilder : ITransientDependency await _backgroundJobRepository.InsertAsync( new BackgroundJobRecord(_testData.JobId3) { + ApplicationName = "App1", JobName = "TestJobName", JobArgs = "{ value: 3 }", NextTryTime = _clock.Now,