diff --git a/.cursor/hooks/state/continual-learning-index.json b/.cursor/hooks/state/continual-learning-index.json new file mode 100644 index 0000000000..43a36a8c73 --- /dev/null +++ b/.cursor/hooks/state/continual-learning-index.json @@ -0,0 +1,9 @@ +{ + "version": 1, + "transcripts": { + "C:\\Users\\salih\\.cursor\\projects\\d-GitHub2-abp\\agent-transcripts\\ded34ec4-ff99-404a-8b16-10baf3c5d9f5\\ded34ec4-ff99-404a-8b16-10baf3c5d9f5.jsonl": { + "mtimeMs": 1773090599259, + "lastProcessedAt": "2026-03-10T00:18:00.000Z" + } + } +} diff --git a/.cursor/hooks/state/continual-learning.json b/.cursor/hooks/state/continual-learning.json new file mode 100644 index 0000000000..a24cb999b0 --- /dev/null +++ b/.cursor/hooks/state/continual-learning.json @@ -0,0 +1,8 @@ +{ + "version": 1, + "lastRunAtMs": 1773090515725, + "turnsSinceLastRun": 5, + "lastTranscriptMtimeMs": 1773090515368, + "lastProcessedGenerationId": "b1b803a9-44bb-4047-a116-4c108a6dadd1", + "trialStartedAtMs": null +} 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 10cacce13e..b10b9cec0e 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 @@ -2,6 +2,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.Immutable; +using System.Threading; using System.Threading.Tasks; namespace Volo.Abp.BackgroundJobs; @@ -10,6 +11,7 @@ public class AbpBackgroundJobOptions { private readonly Dictionary _jobConfigurationsByArgsType; private readonly ConcurrentDictionary _jobConfigurationsByName; + private readonly ConcurrentDictionary> _anonymousHandlers = new(); /// /// Default: true. @@ -60,7 +62,7 @@ public class AbpBackgroundJobOptions public BackgroundJobConfiguration? GetJobOrNull(string name) { - return _jobConfigurationsByName.GetValueOrDefault(name); + return _jobConfigurationsByName.TryGetValue(name, out var config) ? config : null; } public IReadOnlyList GetJobs() @@ -84,28 +86,30 @@ public class AbpBackgroundJobOptions _jobConfigurationsByName[jobConfiguration.JobName] = jobConfiguration; } - public void AddDynamicJob(string jobName, Func handler) + public void AddAnonymousJobHandler(string jobName, Func handler) { - var config = new BackgroundJobConfiguration(jobName, handler); - _jobConfigurationsByName[jobName] = config; + Check.NotNullOrWhiteSpace(jobName, nameof(jobName)); + Check.NotNull(handler, nameof(handler)); + + _anonymousHandlers[jobName] = handler; } - public void AddDynamicJob(string jobName, Action handler) + public void AddAnonymousJobHandler(string jobName, Action handler) { - AddDynamicJob(jobName, context => + AddAnonymousJobHandler(jobName, (jsonData, sp, ct) => { - handler(context); + handler(jsonData, sp, ct); return Task.CompletedTask; }); } - public bool RemoveDynamicJob(string name) + internal bool TryGetAnonymousHandler(string jobName, out Func? handler) { - if (_jobConfigurationsByName.TryGetValue(name, out var config) && config.IsDynamic) - { - return _jobConfigurationsByName.TryRemove(name, out _); - } + return _anonymousHandlers.TryGetValue(jobName, out handler); + } - return false; + internal bool IsAnonymousJobRegistered(string jobName) + { + return _anonymousHandlers.ContainsKey(jobName); } } diff --git a/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/AnonymousJobArgs.cs b/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/AnonymousJobArgs.cs new file mode 100644 index 0000000000..09bac99878 --- /dev/null +++ b/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/AnonymousJobArgs.cs @@ -0,0 +1,17 @@ +namespace Volo.Abp.BackgroundJobs; + +[BackgroundJobName("AnonymousJob")] +public class AnonymousJobArgs +{ + public const string JobNameConstant = "AnonymousJob"; + + public string JobName { get; } + + public string JsonData { get; } + + public AnonymousJobArgs(string jobName, string jsonData) + { + JobName = Check.NotNullOrWhiteSpace(jobName, nameof(jobName)); + JsonData = Check.NotNull(jsonData, nameof(jsonData)); + } +} diff --git a/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/AnonymousJobHandlerRegistry.cs b/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/AnonymousJobHandlerRegistry.cs new file mode 100644 index 0000000000..66c8f95ec2 --- /dev/null +++ b/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/AnonymousJobHandlerRegistry.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Concurrent; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Options; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.BackgroundJobs; + +public class AnonymousJobHandlerRegistry : IAnonymousJobHandlerRegistry, ISingletonDependency +{ + private readonly ConcurrentDictionary> _handlers = new(); + private readonly AbpBackgroundJobOptions _options; + + public AnonymousJobHandlerRegistry(IOptions options) + { + _options = options.Value; + } + + public virtual void Register(string jobName, Func handler) + { + Check.NotNullOrWhiteSpace(jobName, nameof(jobName)); + Check.NotNull(handler, nameof(handler)); + + _handlers[jobName] = handler; + } + + public virtual void Register(string jobName, Action handler) + { + Register(jobName, (jsonData, sp, ct) => + { + handler(jsonData, sp, ct); + return Task.CompletedTask; + }); + } + + public virtual bool Unregister(string jobName) + { + return _handlers.TryRemove(jobName, out _); + } + + public virtual bool IsRegistered(string jobName) + { + return _handlers.ContainsKey(jobName) || _options.IsAnonymousJobRegistered(jobName); + } + + public virtual Func? Get(string jobName) + { + if (_handlers.TryGetValue(jobName, out var handler)) + { + return handler; + } + + return _options.TryGetAnonymousHandler(jobName, out handler) ? handler : null; + } +} diff --git a/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/BackgroundJobConfiguration.cs b/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/BackgroundJobConfiguration.cs index cd0e844a99..fa54ab5538 100644 --- a/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/BackgroundJobConfiguration.cs +++ b/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/BackgroundJobConfiguration.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Threading.Tasks; namespace Volo.Abp.BackgroundJobs; @@ -8,29 +6,14 @@ public class BackgroundJobConfiguration { public Type ArgsType { get; } - public Type? JobType { get; } + public Type JobType { get; } public string JobName { get; } - public bool IsDynamic { get; } - - public Func? DynamicHandler { get; } - public BackgroundJobConfiguration(Type jobType, string jobName) { JobType = jobType; ArgsType = BackgroundJobArgsHelper.GetJobArgsType(jobType); JobName = jobName; } - - public BackgroundJobConfiguration(string jobName, Func handler) - { - Check.NotNullOrWhiteSpace(jobName, nameof(jobName)); - Check.NotNull(handler, nameof(handler)); - - JobName = jobName; - DynamicHandler = handler; - IsDynamic = true; - ArgsType = typeof(Dictionary); - } } diff --git a/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/BackgroundJobExecuter.cs b/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/BackgroundJobExecuter.cs index d84845ee0f..0170b881df 100644 --- a/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/BackgroundJobExecuter.cs +++ b/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/BackgroundJobExecuter.cs @@ -2,8 +2,6 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Options; using System; -using System.Collections.Generic; -using System.Text.Json; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Volo.Abp.DependencyInjection; @@ -31,54 +29,9 @@ public class BackgroundJobExecuter : IBackgroundJobExecuter, ITransientDependenc public virtual async Task ExecuteAsync(JobExecutionContext context) { - if (context.JobName != null) - { - var jobConfig = Options.GetJobOrNull(context.JobName); - if (jobConfig?.DynamicHandler != null) - { - await ExecuteDynamicHandlerAsync(context, jobConfig); - return; - } - } - await ExecuteTypedHandlerAsync(context); } - protected virtual async Task ExecuteDynamicHandlerAsync(JobExecutionContext context, BackgroundJobConfiguration jobConfig) - { - try - { - var cancellationTokenProvider = - context.ServiceProvider.GetRequiredService(); - - using (cancellationTokenProvider.Use(context.CancellationToken)) - { - var dictArgs = EnsureDictionaryArgs(context.JobArgs); - var dynamicContext = new DynamicBackgroundJobContext( - context.ServiceProvider, - dictArgs, - context.CancellationToken - ); - - await jobConfig.DynamicHandler!(dynamicContext); - } - } - catch (Exception ex) - { - Logger.LogException(ex); - - await context.ServiceProvider - .GetRequiredService() - .NotifyAsync(new ExceptionNotificationContext(ex)); - - throw new BackgroundJobExecutionException("A background job execution is failed. See inner exception for details.", ex) - { - JobType = context.JobName!, - JobArgs = context.JobArgs - }; - } - } - protected virtual async Task ExecuteTypedHandlerAsync(JobExecutionContext context) { var job = context.ServiceProvider.GetService(context.JobType); @@ -131,24 +84,6 @@ public class BackgroundJobExecuter : IBackgroundJobExecuter, ITransientDependenc } } - protected virtual Dictionary EnsureDictionaryArgs(object jobArgs) - { - if (jobArgs is Dictionary dict) - { - return dict; - } - - if (jobArgs is JsonElement jsonElement) - { - return JsonSerializer.Deserialize>(jsonElement.GetRawText()) - ?? new Dictionary(); - } - - var json = JsonSerializer.Serialize(jobArgs); - return JsonSerializer.Deserialize>(json) - ?? new Dictionary(); - } - protected virtual Guid? GetJobArgsTenantId(object jobArgs) { return jobArgs switch diff --git a/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/DynamicBackgroundJobContext.cs b/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/DynamicBackgroundJobContext.cs deleted file mode 100644 index 49ffe89aca..0000000000 --- a/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/DynamicBackgroundJobContext.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading; -using Volo.Abp.DependencyInjection; - -namespace Volo.Abp.BackgroundJobs; - -public class DynamicBackgroundJobContext : IServiceProviderAccessor -{ - public IServiceProvider ServiceProvider { get; } - - public Dictionary Args { get; } - - public CancellationToken CancellationToken { get; } - - public DynamicBackgroundJobContext( - IServiceProvider serviceProvider, - Dictionary args, - CancellationToken cancellationToken = default) - { - ServiceProvider = serviceProvider; - Args = args; - CancellationToken = cancellationToken; - } -} diff --git a/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/DynamicBackgroundJobHandlerProvider.cs b/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/DynamicBackgroundJobHandlerProvider.cs deleted file mode 100644 index 2665719c2a..0000000000 --- a/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/DynamicBackgroundJobHandlerProvider.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Threading.Tasks; -using Microsoft.Extensions.Options; -using Volo.Abp.DependencyInjection; - -namespace Volo.Abp.BackgroundJobs; - -public class DynamicBackgroundJobHandlerProvider : IDynamicBackgroundJobHandlerProvider, ISingletonDependency -{ - protected AbpBackgroundJobOptions Options { get; } - - public DynamicBackgroundJobHandlerProvider(IOptions options) - { - Options = options.Value; - } - - public virtual void Register(string jobName, Func handler) - { - Options.AddDynamicJob(jobName, handler); - } - - public virtual void Register(string jobName, Action handler) - { - Options.AddDynamicJob(jobName, handler); - } - - public virtual bool Unregister(string jobName) - { - return Options.RemoveDynamicJob(jobName); - } - - public virtual bool IsRegistered(string jobName) - { - return Options.GetJobOrNull(jobName)?.IsDynamic == true; - } -} diff --git a/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/IAnonymousJobHandlerRegistry.cs b/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/IAnonymousJobHandlerRegistry.cs new file mode 100644 index 0000000000..e02c09ab28 --- /dev/null +++ b/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/IAnonymousJobHandlerRegistry.cs @@ -0,0 +1,18 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; + +namespace Volo.Abp.BackgroundJobs; + +public interface IAnonymousJobHandlerRegistry +{ + void Register(string jobName, Func handler); + + void Register(string jobName, Action handler); + + bool Unregister(string jobName); + + bool IsRegistered(string jobName); + + Func? Get(string jobName); +} diff --git a/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/IDynamicBackgroundJobHandlerProvider.cs b/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/IDynamicBackgroundJobHandlerProvider.cs deleted file mode 100644 index 0f1bb8449a..0000000000 --- a/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/IDynamicBackgroundJobHandlerProvider.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Threading.Tasks; - -namespace Volo.Abp.BackgroundJobs; - -public interface IDynamicBackgroundJobHandlerProvider -{ - void Register(string jobName, Func handler); - - void Register(string jobName, Action handler); - - bool Unregister(string jobName); - - bool IsRegistered(string jobName); -} diff --git a/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/JobExecutionContext.cs b/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/JobExecutionContext.cs index a68736bb7d..4ef2d2c19d 100644 --- a/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/JobExecutionContext.cs +++ b/framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/JobExecutionContext.cs @@ -14,19 +14,15 @@ public class JobExecutionContext : IServiceProviderAccessor public CancellationToken CancellationToken { get; } - public string? JobName { get; } - public JobExecutionContext( IServiceProvider serviceProvider, Type jobType, object jobArgs, - CancellationToken cancellationToken = default, - string? jobName = null) + CancellationToken cancellationToken = default) { ServiceProvider = serviceProvider; JobType = jobType; JobArgs = jobArgs; CancellationToken = cancellationToken; - JobName = jobName; } } 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 840b546783..fbd1034ecd 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 @@ -16,15 +16,18 @@ public class HangfireBackgroundJobManager : IBackgroundJobManager, ITransientDep protected IOptions BackgroundJobOptions { get; } protected IOptions HangfireOptions { get; } protected IJsonSerializer JsonSerializer { get; } + protected IAnonymousJobHandlerRegistry AnonymousJobHandlerRegistry { get; } public HangfireBackgroundJobManager( IOptions backgroundJobOptions, IOptions hangfireOptions, - IJsonSerializer jsonSerializer) + IJsonSerializer jsonSerializer, + IAnonymousJobHandlerRegistry anonymousJobHandlerRegistry) { BackgroundJobOptions = backgroundJobOptions; HangfireOptions = hangfireOptions; JsonSerializer = jsonSerializer; + AnonymousJobHandlerRegistry = anonymousJobHandlerRegistry; } public virtual Task EnqueueAsync(TArgs args, BackgroundJobPriority priority = BackgroundJobPriority.Normal, @@ -43,6 +46,13 @@ public class HangfireBackgroundJobManager : IBackgroundJobManager, ITransientDep public virtual Task EnqueueAsync(string jobName, object args, BackgroundJobPriority priority = BackgroundJobPriority.Normal, TimeSpan? delay = null) { + if (ShouldWrapAsAnonymousJob(jobName)) + { + var jsonData = JsonSerializer.Serialize(args); + var anonymousArgs = new AnonymousJobArgs(jobName, jsonData); + return EnqueueAsync(AnonymousJobArgs.JobNameConstant, anonymousArgs, priority, delay); + } + var serializedArgs = JsonSerializer.Serialize(args); var queueName = GetQueueName(jobName); @@ -56,6 +66,11 @@ public class HangfireBackgroundJobManager : IBackgroundJobManager, ITransientDep )); } + protected virtual bool ShouldWrapAsAnonymousJob(string jobName) + { + return jobName != AnonymousJobArgs.JobNameConstant && AnonymousJobHandlerRegistry.IsRegistered(jobName); + } + protected virtual string GetQueueName(Type argsType) { return GetQueueName(BackgroundJobOptions.Value.GetJob(argsType)); 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 b85154a5c3..38d6bbdf52 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 @@ -40,7 +40,7 @@ public class HangfireJobExecutionAdapter using (var scope = ServiceScopeFactory.CreateScope()) { var jobConfiguration = Options.GetJob(typeof(TArgs)); - var context = new JobExecutionContext(scope.ServiceProvider, jobConfiguration.JobType!, args!, cancellationToken: cancellationToken, jobName: jobConfiguration.JobName); + var context = new JobExecutionContext(scope.ServiceProvider, jobConfiguration.JobType!, args!, cancellationToken: cancellationToken); await JobExecuter.ExecuteAsync(context); } } @@ -83,7 +83,7 @@ public class HangfireJobExecutionAdapter { var jobConfiguration = Options.GetJob(jobName); var args = JsonSerializer.Deserialize(jobConfiguration.ArgsType, serializedArgs); - var context = new JobExecutionContext(scope.ServiceProvider, jobConfiguration.JobType ?? typeof(object), args, cancellationToken: cancellationToken, jobName: jobName); + var context = new JobExecutionContext(scope.ServiceProvider, jobConfiguration.JobType, args, cancellationToken: cancellationToken); await JobExecuter.ExecuteAsync(context); } } 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 dd8e385246..842f47c78f 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 @@ -19,11 +19,14 @@ public class QuartzBackgroundJobManager : IBackgroundJobManager, ITransientDepen protected IJsonSerializer JsonSerializer { get; } - public QuartzBackgroundJobManager(IScheduler scheduler, IOptions options, IJsonSerializer jsonSerializer) + protected IAnonymousJobHandlerRegistry AnonymousJobHandlerRegistry { get; } + + public QuartzBackgroundJobManager(IScheduler scheduler, IOptions options, IJsonSerializer jsonSerializer, IAnonymousJobHandlerRegistry anonymousJobHandlerRegistry) { Scheduler = scheduler; JsonSerializer = jsonSerializer; Options = options.Value; + AnonymousJobHandlerRegistry = anonymousJobHandlerRegistry; } public virtual async Task EnqueueAsync(TArgs args, BackgroundJobPriority priority = BackgroundJobPriority.Normal, @@ -35,9 +38,21 @@ public class QuartzBackgroundJobManager : IBackgroundJobManager, ITransientDepen public virtual async Task EnqueueAsync(string jobName, object args, BackgroundJobPriority priority = BackgroundJobPriority.Normal, TimeSpan? delay = null) { + if (ShouldWrapAsAnonymousJob(jobName)) + { + var jsonData = JsonSerializer.Serialize(args); + var anonymousArgs = new AnonymousJobArgs(jobName, jsonData); + return await EnqueueAsync(AnonymousJobArgs.JobNameConstant, anonymousArgs, priority, delay); + } + return await ReEnqueueAsync(jobName, args, Options.RetryCount, Options.RetryIntervalMillisecond, priority, delay); } + protected virtual bool ShouldWrapAsAnonymousJob(string jobName) + { + return jobName != AnonymousJobArgs.JobNameConstant && AnonymousJobHandlerRegistry.IsRegistered(jobName); + } + public virtual async Task ReEnqueueAsync(TArgs args, int retryCount, int retryIntervalMillisecond, BackgroundJobPriority priority = BackgroundJobPriority.Normal, TimeSpan? delay = null) { 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 defdb87031..d6e690dcff 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 @@ -97,7 +97,7 @@ public class QuartzJobExecutionAdapter : IJob var serializedArgs = context.JobDetail.JobDataMap.GetString(JobArgsKey)!; var jobConfiguration = Options.GetJob(jobName); var args = JsonSerializer.Deserialize(jobConfiguration.ArgsType, serializedArgs); - var jobContext = new JobExecutionContext(scope.ServiceProvider, jobConfiguration.JobType ?? typeof(object), args, cancellationToken: context.CancellationToken, jobName: jobName); + var jobContext = new JobExecutionContext(scope.ServiceProvider, jobConfiguration.JobType, args, cancellationToken: context.CancellationToken); try { await JobExecuter.ExecuteAsync(jobContext); diff --git a/framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/JobQueue.cs b/framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/JobQueue.cs index be7614060d..33c41704f2 100644 --- a/framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/JobQueue.cs +++ b/framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/JobQueue.cs @@ -214,9 +214,8 @@ public class JobQueue : IJobQueue { var context = new JobExecutionContext( scope.ServiceProvider, - JobConfiguration.JobType ?? typeof(object), - Serializer.Deserialize(ea.Body.ToArray(), typeof(TArgs)), - jobName: JobConfiguration.JobName + JobConfiguration.JobType, + Serializer.Deserialize(ea.Body.ToArray(), typeof(TArgs)) ); try diff --git a/framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/RabbitMqBackgroundJobManager.cs b/framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/RabbitMqBackgroundJobManager.cs index 69ac3c0a62..5c7b420c98 100644 --- a/framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/RabbitMqBackgroundJobManager.cs +++ b/framework/src/Volo.Abp.BackgroundJobs.RabbitMQ/Volo/Abp/BackgroundJobs/RabbitMQ/RabbitMqBackgroundJobManager.cs @@ -1,6 +1,7 @@ using System; using System.Threading.Tasks; using Volo.Abp.DependencyInjection; +using Volo.Abp.Json; namespace Volo.Abp.BackgroundJobs.RabbitMQ; @@ -8,10 +9,14 @@ namespace Volo.Abp.BackgroundJobs.RabbitMQ; public class RabbitMqBackgroundJobManager : IBackgroundJobManager, ITransientDependency { protected IJobQueueManager JobQueueManager { get; } + protected IAnonymousJobHandlerRegistry AnonymousJobHandlerRegistry { get; } + protected IJsonSerializer JsonSerializer { get; } - public RabbitMqBackgroundJobManager(IJobQueueManager jobQueueManager) + public RabbitMqBackgroundJobManager(IJobQueueManager jobQueueManager, IAnonymousJobHandlerRegistry anonymousJobHandlerRegistry, IJsonSerializer jsonSerializer) { JobQueueManager = jobQueueManager; + AnonymousJobHandlerRegistry = anonymousJobHandlerRegistry; + JsonSerializer = jsonSerializer; } public virtual async Task EnqueueAsync( @@ -29,7 +34,19 @@ public class RabbitMqBackgroundJobManager : IBackgroundJobManager, ITransientDep BackgroundJobPriority priority = BackgroundJobPriority.Normal, TimeSpan? delay = null) { + if (ShouldWrapAsAnonymousJob(jobName)) + { + var jsonData = JsonSerializer.Serialize(args); + var anonymousArgs = new AnonymousJobArgs(jobName, jsonData); + return await EnqueueAsync(AnonymousJobArgs.JobNameConstant, anonymousArgs, priority, delay); + } + var jobQueue = await JobQueueManager.GetAsync(jobName); return (await jobQueue.EnqueueAsync(args, priority, delay))!; } + + protected virtual bool ShouldWrapAsAnonymousJob(string jobName) + { + return jobName != AnonymousJobArgs.JobNameConstant && AnonymousJobHandlerRegistry.IsRegistered(jobName); + } } diff --git a/framework/src/Volo.Abp.BackgroundJobs.TickerQ/Volo/Abp/BackgroundJobs/TickerQ/AbpBackgroundJobsTickerQModule.cs b/framework/src/Volo.Abp.BackgroundJobs.TickerQ/Volo/Abp/BackgroundJobs/TickerQ/AbpBackgroundJobsTickerQModule.cs index 915e061057..1cde94b517 100644 --- a/framework/src/Volo.Abp.BackgroundJobs.TickerQ/Volo/Abp/BackgroundJobs/TickerQ/AbpBackgroundJobsTickerQModule.cs +++ b/framework/src/Volo.Abp.BackgroundJobs.TickerQ/Volo/Abp/BackgroundJobs/TickerQ/AbpBackgroundJobsTickerQModule.cs @@ -67,7 +67,7 @@ public class AbpBackgroundJobsTickerQModule : AbpModule var jobExecuter = serviceProvider.GetRequiredService(); var args = await TickerRequestProvider.GetRequestAsync(context, cancellationToken); var jobConfiguration = options.GetJob(typeof(TArgs)); - var jobExecutionContext = new JobExecutionContext(scope.ServiceProvider, jobConfiguration.JobType ?? typeof(object), args!, cancellationToken: cancellationToken, jobName: jobConfiguration.JobName); + var jobExecutionContext = new JobExecutionContext(scope.ServiceProvider, jobConfiguration.JobType, args!, cancellationToken: cancellationToken); await jobExecuter.ExecuteAsync(jobExecutionContext); } }; diff --git a/framework/src/Volo.Abp.BackgroundJobs.TickerQ/Volo/Abp/BackgroundJobs/TickerQ/AbpTickerQBackgroundJobManager.cs b/framework/src/Volo.Abp.BackgroundJobs.TickerQ/Volo/Abp/BackgroundJobs/TickerQ/AbpTickerQBackgroundJobManager.cs index f70e48fcf5..0b4557f09c 100644 --- a/framework/src/Volo.Abp.BackgroundJobs.TickerQ/Volo/Abp/BackgroundJobs/TickerQ/AbpTickerQBackgroundJobManager.cs +++ b/framework/src/Volo.Abp.BackgroundJobs.TickerQ/Volo/Abp/BackgroundJobs/TickerQ/AbpTickerQBackgroundJobManager.cs @@ -6,6 +6,7 @@ using TickerQ.Utilities; using TickerQ.Utilities.Entities; using TickerQ.Utilities.Interfaces.Managers; using Volo.Abp.DependencyInjection; +using Volo.Abp.Json; namespace Volo.Abp.BackgroundJobs.TickerQ; @@ -17,15 +18,21 @@ public class AbpTickerQBackgroundJobManager : IBackgroundJobManager, ITransientD protected ITimeTickerManager TimeTickerManager { get; } protected AbpBackgroundJobOptions Options { get; } protected AbpBackgroundJobsTickerQOptions TickerQOptions { get; } + protected IAnonymousJobHandlerRegistry AnonymousJobHandlerRegistry { get; } + protected IJsonSerializer JsonSerializer { get; } public AbpTickerQBackgroundJobManager( ITimeTickerManager timeTickerManager, IOptions options, - IOptions tickerQOptions) + IOptions tickerQOptions, + IAnonymousJobHandlerRegistry anonymousJobHandlerRegistry, + IJsonSerializer jsonSerializer) { TimeTickerManager = timeTickerManager; Options = options.Value; TickerQOptions = tickerQOptions.Value; + AnonymousJobHandlerRegistry = anonymousJobHandlerRegistry; + JsonSerializer = jsonSerializer; } public virtual async Task EnqueueAsync(TArgs args, BackgroundJobPriority priority = BackgroundJobPriority.Normal, TimeSpan? delay = null) @@ -36,10 +43,22 @@ public class AbpTickerQBackgroundJobManager : IBackgroundJobManager, ITransientD public virtual async Task EnqueueAsync(string jobName, object args, BackgroundJobPriority priority = BackgroundJobPriority.Normal, TimeSpan? delay = null) { + if (ShouldWrapAsAnonymousJob(jobName)) + { + var jsonData = JsonSerializer.Serialize(args); + var anonymousArgs = new AnonymousJobArgs(jobName, jsonData); + return await EnqueueAsync(AnonymousJobArgs.JobNameConstant, anonymousArgs, priority, delay); + } + var job = Options.GetJob(jobName); return await EnqueueAsync(job, args, priority, delay); } + protected virtual bool ShouldWrapAsAnonymousJob(string jobName) + { + return jobName != AnonymousJobArgs.JobNameConstant && AnonymousJobHandlerRegistry.IsRegistered(jobName); + } + protected virtual async Task EnqueueAsync(BackgroundJobConfiguration job, object args, BackgroundJobPriority priority, TimeSpan? delay) { var timeTicker = new TimeTickerEntity diff --git a/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/AnonymousJobExecutorAsyncBackgroundJob.cs b/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/AnonymousJobExecutorAsyncBackgroundJob.cs new file mode 100644 index 0000000000..6bc0c594c7 --- /dev/null +++ b/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/AnonymousJobExecutorAsyncBackgroundJob.cs @@ -0,0 +1,35 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Threading; + +namespace Volo.Abp.BackgroundJobs; + +public class AnonymousJobExecutorAsyncBackgroundJob : AsyncBackgroundJob, ITransientDependency +{ + protected IAnonymousJobHandlerRegistry HandlerRegistry { get; } + protected IServiceProvider ServiceProvider { get; } + protected ICancellationTokenProvider CancellationTokenProvider { get; } + + public AnonymousJobExecutorAsyncBackgroundJob( + IAnonymousJobHandlerRegistry handlerRegistry, + IServiceProvider serviceProvider, + ICancellationTokenProvider cancellationTokenProvider) + { + HandlerRegistry = handlerRegistry; + ServiceProvider = serviceProvider; + CancellationTokenProvider = cancellationTokenProvider; + } + + public override async Task ExecuteAsync(AnonymousJobArgs args) + { + var handler = HandlerRegistry.Get(args.JobName); + if (handler == null) + { + throw new AbpException("No anonymous job handler registered for: " + args.JobName); + } + + await handler(args.JsonData, ServiceProvider, CancellationTokenProvider.Token); + } +} 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 930beecd5c..159f11a6d3 100644 --- a/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/BackgroundJobWorker.cs +++ b/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/BackgroundJobWorker.cs @@ -65,10 +65,9 @@ public class BackgroundJobWorker : AsyncPeriodicBackgroundWorkerBase, IBackgroun var jobArgs = serializer.Deserialize(jobInfo.JobArgs, jobConfiguration.ArgsType); var context = new JobExecutionContext( workerContext.ServiceProvider, - jobConfiguration.JobType ?? typeof(object), + jobConfiguration.JobType, jobArgs, - workerContext.CancellationToken, - jobName: jobInfo.JobName); + workerContext.CancellationToken); try { 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 582d351431..1760342ef1 100644 --- a/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/DefaultBackgroundJobManager.cs +++ b/framework/src/Volo.Abp.BackgroundJobs/Volo/Abp/BackgroundJobs/DefaultBackgroundJobManager.cs @@ -18,6 +18,7 @@ public class DefaultBackgroundJobManager : IBackgroundJobManager, ITransientDepe protected IBackgroundJobSerializer Serializer { get; } protected IGuidGenerator GuidGenerator { get; } protected IBackgroundJobStore Store { get; } + protected IAnonymousJobHandlerRegistry AnonymousJobHandlerRegistry { get; } protected IOptions BackgroundJobOptions { get; } protected IOptions BackgroundJobWorkerOptions { get; } @@ -26,12 +27,14 @@ public class DefaultBackgroundJobManager : IBackgroundJobManager, ITransientDepe IBackgroundJobSerializer serializer, IBackgroundJobStore store, IGuidGenerator guidGenerator, + IAnonymousJobHandlerRegistry anonymousJobHandlerRegistry, IOptions backgroundJobOptions, IOptions backgroundJobWorkerOptions) { Clock = clock; Serializer = serializer; GuidGenerator = guidGenerator; + AnonymousJobHandlerRegistry = anonymousJobHandlerRegistry; BackgroundJobOptions = backgroundJobOptions; BackgroundJobWorkerOptions = backgroundJobWorkerOptions; Store = store; @@ -45,6 +48,13 @@ public class DefaultBackgroundJobManager : IBackgroundJobManager, ITransientDepe public virtual async Task EnqueueAsync(string jobName, object args, BackgroundJobPriority priority = BackgroundJobPriority.Normal, TimeSpan? delay = null) { + if (ShouldWrapAsAnonymousJob(jobName)) + { + var jsonData = Serializer.Serialize(args); + var anonymousArgs = new AnonymousJobArgs(jobName, jsonData); + return await EnqueueAsync(AnonymousJobArgs.JobNameConstant, anonymousArgs, priority, delay); + } + var jobInfo = new BackgroundJobInfo { Id = GuidGenerator.Create(), @@ -65,4 +75,9 @@ public class DefaultBackgroundJobManager : IBackgroundJobManager, ITransientDepe return jobInfo.Id.ToString(); } + + protected virtual bool ShouldWrapAsAnonymousJob(string jobName) + { + return jobName != AnonymousJobArgs.JobNameConstant && AnonymousJobHandlerRegistry.IsRegistered(jobName); + } } diff --git a/framework/test/Volo.Abp.BackgroundJobs.Tests/Volo/Abp/BackgroundJobs/AbpBackgroundJobsTestModule.cs b/framework/test/Volo.Abp.BackgroundJobs.Tests/Volo/Abp/BackgroundJobs/AbpBackgroundJobsTestModule.cs index 14e2c558bd..ee792812ac 100644 --- a/framework/test/Volo.Abp.BackgroundJobs.Tests/Volo/Abp/BackgroundJobs/AbpBackgroundJobsTestModule.cs +++ b/framework/test/Volo.Abp.BackgroundJobs.Tests/Volo/Abp/BackgroundJobs/AbpBackgroundJobsTestModule.cs @@ -13,14 +13,14 @@ public class AbpBackgroundJobsTestModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { - context.Services.AddSingleton(); + context.Services.AddSingleton(); Configure(options => { - options.AddDynamicJob("TestDynamicJob", context => + options.AddAnonymousJobHandler("TestAnonymousJob", (jsonData, sp, ct) => { - var tracker = context.ServiceProvider.GetRequiredService(); - tracker.ExecutedArgs.Add(context.Args); + var tracker = sp.GetRequiredService(); + tracker.ExecutedJsonData.Add(jsonData); return System.Threading.Tasks.Task.CompletedTask; }); }); diff --git a/framework/test/Volo.Abp.BackgroundJobs.Tests/Volo/Abp/BackgroundJobs/AnonymousJobExecutionTracker.cs b/framework/test/Volo.Abp.BackgroundJobs.Tests/Volo/Abp/BackgroundJobs/AnonymousJobExecutionTracker.cs new file mode 100644 index 0000000000..b3160a2829 --- /dev/null +++ b/framework/test/Volo.Abp.BackgroundJobs.Tests/Volo/Abp/BackgroundJobs/AnonymousJobExecutionTracker.cs @@ -0,0 +1,8 @@ +using System.Collections.Generic; + +namespace Volo.Abp.BackgroundJobs; + +public class AnonymousJobExecutionTracker +{ + public List ExecutedJsonData { get; } = new(); +} diff --git a/framework/test/Volo.Abp.BackgroundJobs.Tests/Volo/Abp/BackgroundJobs/BackgroundJobExecuter_Tests.cs b/framework/test/Volo.Abp.BackgroundJobs.Tests/Volo/Abp/BackgroundJobs/BackgroundJobExecuter_Tests.cs index 87f7ff316b..a46e79d15d 100644 --- a/framework/test/Volo.Abp.BackgroundJobs.Tests/Volo/Abp/BackgroundJobs/BackgroundJobExecuter_Tests.cs +++ b/framework/test/Volo.Abp.BackgroundJobs.Tests/Volo/Abp/BackgroundJobs/BackgroundJobExecuter_Tests.cs @@ -139,54 +139,52 @@ public class BackgroundJobExecuter_Tests : BackgroundJobsTestBase } [Fact] - public async Task Should_Execute_Dynamic_Handler() + public async Task Should_Execute_Anonymous_Job_Handler() { - var tracker = GetRequiredService(); - tracker.ExecutedArgs.ShouldBeEmpty(); + var tracker = GetRequiredService(); + tracker.ExecutedJsonData.ShouldBeEmpty(); - var args = new Dictionary { ["Value"] = "dynamic-42" }; + var args = new AnonymousJobArgs("TestAnonymousJob", "{\"OrderId\":\"ORD-001\"}"); await _backgroundJobExecuter.ExecuteAsync( new JobExecutionContext( ServiceProvider, - typeof(object), - args, - jobName: "TestDynamicJob" + typeof(AnonymousJobExecutorAsyncBackgroundJob), + args ) ); - tracker.ExecutedArgs.Count.ShouldBe(1); - tracker.ExecutedArgs[0]["Value"].ShouldBe("dynamic-42"); + tracker.ExecutedJsonData.Count.ShouldBe(1); + tracker.ExecutedJsonData[0].ShouldContain("ORD-001"); } [Fact] - public async Task Should_Execute_Dynamic_Handler_Registered_At_Runtime() + public async Task Should_Execute_Anonymous_Job_Handler_Registered_At_Runtime() { - var handlerProvider = GetRequiredService(); + var handlerRegistry = GetRequiredService(); var executedValues = new List(); - handlerProvider.Register("RuntimeDynamicJob", context => + handlerRegistry.Register("RuntimeAnonymousJob", (jsonData, sp, ct) => { - executedValues.Add(context.Args["Message"]?.ToString()!); + executedValues.Add(jsonData); return Task.CompletedTask; }); - var args = new Dictionary { ["Message"] = "hello-runtime" }; + var args = new AnonymousJobArgs("RuntimeAnonymousJob", "{\"Message\":\"hello-runtime\"}"); await _backgroundJobExecuter.ExecuteAsync( new JobExecutionContext( ServiceProvider, - typeof(object), - args, - jobName: "RuntimeDynamicJob" + typeof(AnonymousJobExecutorAsyncBackgroundJob), + args ) ); executedValues.Count.ShouldBe(1); - executedValues[0].ShouldBe("hello-runtime"); + executedValues[0].ShouldContain("hello-runtime"); - handlerProvider.IsRegistered("RuntimeDynamicJob").ShouldBeTrue(); - handlerProvider.Unregister("RuntimeDynamicJob").ShouldBeTrue(); - handlerProvider.IsRegistered("RuntimeDynamicJob").ShouldBeFalse(); + handlerRegistry.IsRegistered("RuntimeAnonymousJob").ShouldBeTrue(); + handlerRegistry.Unregister("RuntimeAnonymousJob").ShouldBeTrue(); + handlerRegistry.IsRegistered("RuntimeAnonymousJob").ShouldBeFalse(); } } diff --git a/framework/test/Volo.Abp.BackgroundJobs.Tests/Volo/Abp/BackgroundJobs/BackgroundJobManager_Tests.cs b/framework/test/Volo.Abp.BackgroundJobs.Tests/Volo/Abp/BackgroundJobs/BackgroundJobManager_Tests.cs index 75d1218f94..bb8d05bf86 100644 --- a/framework/test/Volo.Abp.BackgroundJobs.Tests/Volo/Abp/BackgroundJobs/BackgroundJobManager_Tests.cs +++ b/framework/test/Volo.Abp.BackgroundJobs.Tests/Volo/Abp/BackgroundJobs/BackgroundJobManager_Tests.cs @@ -64,17 +64,15 @@ public class BackgroundJobManager_Tests : BackgroundJobsTestBase } [Fact] - public async Task Should_Store_Dynamic_Jobs() + public async Task Should_Store_Anonymous_Jobs() { - var jobIdAsString = await _backgroundJobManager.EnqueueAsync("TestDynamicJob", (object)new Dictionary - { - ["OrderId"] = "ORD-001" - }); + var jobIdAsString = await _backgroundJobManager.EnqueueAsync("TestAnonymousJob", new { OrderId = "ORD-001" }); jobIdAsString.ShouldNotBe(default); var jobInfo = await _backgroundJobStore.FindAsync(Guid.Parse(jobIdAsString)); jobInfo.ShouldNotBeNull(); - jobInfo.JobName.ShouldBe("TestDynamicJob"); + jobInfo.JobName.ShouldBe(AnonymousJobArgs.JobNameConstant); + jobInfo.JobArgs.ShouldContain("TestAnonymousJob"); jobInfo.JobArgs.ShouldContain("ORD-001"); } } diff --git a/framework/test/Volo.Abp.BackgroundJobs.Tests/Volo/Abp/BackgroundJobs/DynamicJobExecutionTracker.cs b/framework/test/Volo.Abp.BackgroundJobs.Tests/Volo/Abp/BackgroundJobs/DynamicJobExecutionTracker.cs deleted file mode 100644 index dec387ab97..0000000000 --- a/framework/test/Volo.Abp.BackgroundJobs.Tests/Volo/Abp/BackgroundJobs/DynamicJobExecutionTracker.cs +++ /dev/null @@ -1,8 +0,0 @@ -using System.Collections.Generic; - -namespace Volo.Abp.BackgroundJobs; - -public class DynamicJobExecutionTracker -{ - public List> ExecutedArgs { get; } = new(); -} diff --git a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.Shared/DemoAppSharedModule.cs b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.Shared/DemoAppSharedModule.cs index 47da99d683..58046b6313 100644 --- a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.Shared/DemoAppSharedModule.cs +++ b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.Shared/DemoAppSharedModule.cs @@ -1,4 +1,5 @@ using System; +using System.Text.Json; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Volo.Abp.BackgroundJobs.DemoApp.Shared.Jobs; @@ -14,11 +15,11 @@ namespace Volo.Abp.BackgroundJobs.DemoApp.Shared { Configure(options => { - options.AddDynamicJob("CompileTimeDynamicJob", dynamicContext => + options.AddAnonymousJobHandler("CompileTimeAnonymousJob", (jsonData, sp, ct) => { - dynamicContext.Args.TryGetValue("Value", out var valueObj); - var value = valueObj?.ToString(); - Console.WriteLine($"[DYNAMIC-COMPILE] {value}"); + var doc = JsonDocument.Parse(jsonData); + var value = doc.RootElement.TryGetProperty("Value", out var prop) ? prop.GetString() : null; + Console.WriteLine($"[ANONYMOUS-COMPILE] {value}"); return Task.CompletedTask; }); }); diff --git a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.Shared/Jobs/SampleJobCreator.cs b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.Shared/Jobs/SampleJobCreator.cs index a9ceca9bdd..485468582b 100644 --- a/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.Shared/Jobs/SampleJobCreator.cs +++ b/modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.Shared/Jobs/SampleJobCreator.cs @@ -1,5 +1,5 @@ using System; -using System.Collections.Generic; +using System.Text.Json; using System.Threading.Tasks; using Volo.Abp.DependencyInjection; using Volo.Abp.Threading; @@ -9,14 +9,14 @@ namespace Volo.Abp.BackgroundJobs.DemoApp.Shared.Jobs public class SampleJobCreator : ITransientDependency { private readonly IBackgroundJobManager _backgroundJobManager; - private readonly IDynamicBackgroundJobHandlerProvider _dynamicBackgroundJobHandlerProvider; + private readonly IAnonymousJobHandlerRegistry _anonymousJobHandlerRegistry; public SampleJobCreator( IBackgroundJobManager backgroundJobManager, - IDynamicBackgroundJobHandlerProvider dynamicBackgroundJobHandlerProvider) + IAnonymousJobHandlerRegistry anonymousJobHandlerRegistry) { _backgroundJobManager = backgroundJobManager; - _dynamicBackgroundJobHandlerProvider = dynamicBackgroundJobHandlerProvider; + _anonymousJobHandlerRegistry = anonymousJobHandlerRegistry; } public void CreateJobs() @@ -26,10 +26,11 @@ namespace Volo.Abp.BackgroundJobs.DemoApp.Shared.Jobs public async Task CreateJobsAsync() { - _dynamicBackgroundJobHandlerProvider.Register("RuntimeDynamicJob", context => + _anonymousJobHandlerRegistry.Register("RuntimeAnonymousJob", (jsonData, sp, ct) => { - context.Args.TryGetValue("Value", out var valueObj); - Console.WriteLine($"[DYNAMIC-RUNTIME] {valueObj}"); + var doc = JsonDocument.Parse(jsonData); + var value = doc.RootElement.TryGetProperty("Value", out var prop) ? prop.GetString() : null; + Console.WriteLine($"[ANONYMOUS-RUNTIME] {value}"); return Task.CompletedTask; }); @@ -57,16 +58,16 @@ namespace Volo.Abp.BackgroundJobs.DemoApp.Shared.Jobs (object)new { Value = "test 3 (yellow) - by name, anonymous", Time = DateTime.Now } ); - // Dynamic enqueue (compile-time and runtime handlers) - if (!_backgroundJobManager.GetType().Name.Contains("RabbitMq", StringComparison.OrdinalIgnoreCase)) + // Anonymous job enqueue (compile-time and runtime handlers) + if (!_backgroundJobManager.GetType().Name.ToUpperInvariant().Contains("RABBITMQ")) { await _backgroundJobManager.EnqueueAsync( - "CompileTimeDynamicJob", - (object)new Dictionary { ["Value"] = "test 4 (dynamic) - compile-time" } + "CompileTimeAnonymousJob", + new { Value = "test 4 (anonymous) - compile-time" } ); await _backgroundJobManager.EnqueueAsync( - "RuntimeDynamicJob", - (object)new Dictionary { ["Value"] = "test 5 (dynamic) - runtime" } + "RuntimeAnonymousJob", + new { Value = "test 5 (anonymous) - runtime" } ); } } diff --git a/modules/background-jobs/app/docker-compose.yml b/modules/background-jobs/app/docker-compose.yml new file mode 100644 index 0000000000..613711d0b7 --- /dev/null +++ b/modules/background-jobs/app/docker-compose.yml @@ -0,0 +1,25 @@ +services: + sqlserver: + image: mcr.microsoft.com/mssql/server:2022-latest + environment: + ACCEPT_EULA: "Y" + MSSQL_SA_PASSWORD: "YourStrong!Passw0rd" + ports: + - "1433:1433" + volumes: + - sqlserver-data:/var/opt/mssql + + rabbitmq: + image: rabbitmq:4-management + ports: + - "5672:5672" + - "15672:15672" + environment: + RABBITMQ_DEFAULT_USER: "guest" + RABBITMQ_DEFAULT_PASS: "guest" + volumes: + - rabbitmq-data:/var/lib/rabbitmq + +volumes: + sqlserver-data: + rabbitmq-data: