Browse Source

Fix dynamic background job code review issues

pull/25059/head
maliming 6 months ago
parent
commit
7c95bd6796
No known key found for this signature in database GPG Key ID: A646B9CB645ECEA4
  1. 42
      framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/DefaultDynamicBackgroundJobManager.cs
  2. 2
      framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/DynamicBackgroundJobArgs.cs
  3. 23
      framework/test/Volo.Abp.BackgroundJobs.Tests/Volo/Abp/BackgroundJobs/BackgroundJobManager_Tests.cs
  4. 4
      framework/test/Volo.Abp.BackgroundJobs.Tests/Volo/Abp/BackgroundJobs/DynamicJobExecutionTracker.cs

42
framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/DefaultDynamicBackgroundJobManager.cs

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Linq; using System.Linq;
using System.Linq.Expressions;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
@ -11,7 +12,7 @@ namespace Volo.Abp.BackgroundJobs;
public class DefaultDynamicBackgroundJobManager : IDynamicBackgroundJobManager, ITransientDependency public class DefaultDynamicBackgroundJobManager : IDynamicBackgroundJobManager, ITransientDependency
{ {
private static readonly ConcurrentDictionary<Type, MethodInfo> EnqueueMethodCache = new(); private static readonly ConcurrentDictionary<Type, Func<IBackgroundJobManager, object, BackgroundJobPriority, TimeSpan?, Task<string>>> EnqueueDelegateCache = new();
protected IBackgroundJobManager BackgroundJobManager { get; } protected IBackgroundJobManager BackgroundJobManager { get; }
protected IDynamicBackgroundJobHandlerRegistry HandlerRegistry { get; } protected IDynamicBackgroundJobHandlerRegistry HandlerRegistry { get; }
@ -83,9 +84,8 @@ public class DefaultDynamicBackgroundJobManager : IDynamicBackgroundJobManager,
var json = JsonSerializer.Serialize(args); var json = JsonSerializer.Serialize(args);
var typedArgs = JsonSerializer.Deserialize(argsType, json); var typedArgs = JsonSerializer.Deserialize(argsType, json);
var enqueueMethod = GetOrCreateEnqueueMethod(argsType); var enqueueDelegate = GetOrCreateEnqueueDelegate(argsType);
var task = (Task<string>)enqueueMethod.Invoke(BackgroundJobManager, [typedArgs, priority, delay])!; return await enqueueDelegate(BackgroundJobManager, typedArgs, priority, delay);
return await task;
} }
protected virtual Task<string> EnqueueDynamicHandlerJobAsync( protected virtual Task<string> EnqueueDynamicHandlerJobAsync(
@ -99,15 +99,39 @@ public class DefaultDynamicBackgroundJobManager : IDynamicBackgroundJobManager,
return BackgroundJobManager.EnqueueAsync(dynamicArgs, priority, delay); return BackgroundJobManager.EnqueueAsync(dynamicArgs, priority, delay);
} }
private static MethodInfo GetOrCreateEnqueueMethod(Type argsType) private static Func<IBackgroundJobManager, object, BackgroundJobPriority, TimeSpan?, Task<string>> GetOrCreateEnqueueDelegate(Type argsType)
{ {
return EnqueueMethodCache.GetOrAdd(argsType, static type => return EnqueueDelegateCache.GetOrAdd(argsType, static type =>
{ {
var method = typeof(IBackgroundJobManager) var method = typeof(IBackgroundJobManager)
.GetMethods(BindingFlags.Public | BindingFlags.Instance) .GetMethods(BindingFlags.Public | BindingFlags.Instance)
.Single(m => m.Name == nameof(IBackgroundJobManager.EnqueueAsync) && m.IsGenericMethodDefinition); .FirstOrDefault(m => m.Name == nameof(IBackgroundJobManager.EnqueueAsync)
&& m.IsGenericMethodDefinition
return method.MakeGenericMethod(type); && m.GetParameters().Length == 3);
if (method == null)
{
throw new AbpException(
$"Could not find the generic EnqueueAsync method on {nameof(IBackgroundJobManager)}.");
}
var genericMethod = method.MakeGenericMethod(type);
// Build: (manager, args, priority, delay) => manager.EnqueueAsync<TArgs>((TArgs)args, priority, delay)
var managerParam = Expression.Parameter(typeof(IBackgroundJobManager), "manager");
var argsParam = Expression.Parameter(typeof(object), "args");
var priorityParam = Expression.Parameter(typeof(BackgroundJobPriority), "priority");
var delayParam = Expression.Parameter(typeof(TimeSpan?), "delay");
var call = Expression.Call(
managerParam,
genericMethod,
Expression.Convert(argsParam, type),
priorityParam,
delayParam);
return Expression.Lambda<Func<IBackgroundJobManager, object, BackgroundJobPriority, TimeSpan?, Task<string>>>(
call, managerParam, argsParam, priorityParam, delayParam).Compile();
}); });
} }
} }

2
framework/src/Volo.Abp.BackgroundJobs.Abstractions/Volo/Abp/BackgroundJobs/DynamicBackgroundJobArgs.cs

@ -12,6 +12,6 @@ public class DynamicBackgroundJobArgs
public DynamicBackgroundJobArgs(string jobName, string jsonData) public DynamicBackgroundJobArgs(string jobName, string jsonData)
{ {
JobName = Check.NotNullOrWhiteSpace(jobName, nameof(jobName)); JobName = Check.NotNullOrWhiteSpace(jobName, nameof(jobName));
JsonData = Check.NotNull(jsonData, nameof(jsonData)); JsonData = Check.NotNullOrWhiteSpace(jsonData, nameof(jsonData));
} }
} }

23
framework/test/Volo.Abp.BackgroundJobs.Tests/Volo/Abp/BackgroundJobs/BackgroundJobManager_Tests.cs

@ -81,7 +81,7 @@ public class BackgroundJobManager_Tests : BackgroundJobsTestBase
[Fact] [Fact]
public async Task Should_Execute_Dynamic_Handler_Job() public async Task Should_Execute_Dynamic_Handler_Job()
{ {
_tracker.ExecutedJsonData.ShouldBeEmpty(); _tracker.ExecutedJsonData.IsEmpty.ShouldBeTrue();
await _backgroundJobExecuter.ExecuteAsync( await _backgroundJobExecuter.ExecuteAsync(
new JobExecutionContext( new JobExecutionContext(
@ -100,13 +100,20 @@ public class BackgroundJobManager_Tests : BackgroundJobsTestBase
var typedJobName = BackgroundJobNameAttribute.GetName<MyJobArgs>(); var typedJobName = BackgroundJobNameAttribute.GetName<MyJobArgs>();
_dynamicBackgroundJobManager.RegisterHandler(typedJobName, (_, _) => Task.CompletedTask); _dynamicBackgroundJobManager.RegisterHandler(typedJobName, (_, _) => Task.CompletedTask);
var jobIdAsString = await _dynamicBackgroundJobManager.EnqueueAsync(typedJobName, new { Value = "42" }); try
jobIdAsString.ShouldNotBe(default); {
var jobIdAsString = await _dynamicBackgroundJobManager.EnqueueAsync(typedJobName, new { Value = "42" });
var jobInfo = await _backgroundJobStore.FindAsync(Guid.Parse(jobIdAsString)); jobIdAsString.ShouldNotBe(default);
jobInfo.ShouldNotBeNull();
jobInfo.JobName.ShouldBe(typedJobName); var jobInfo = await _backgroundJobStore.FindAsync(Guid.Parse(jobIdAsString));
jobInfo.JobName.ShouldNotBe(DynamicBackgroundJobArgs.JobNameConstant); jobInfo.ShouldNotBeNull();
jobInfo.JobName.ShouldBe(typedJobName);
jobInfo.JobName.ShouldNotBe(DynamicBackgroundJobArgs.JobNameConstant);
}
finally
{
_dynamicBackgroundJobManager.UnregisterHandler(typedJobName);
}
} }
[Fact] [Fact]

4
framework/test/Volo.Abp.BackgroundJobs.Tests/Volo/Abp/BackgroundJobs/DynamicJobExecutionTracker.cs

@ -1,8 +1,8 @@
using System.Collections.Generic; using System.Collections.Concurrent;
namespace Volo.Abp.BackgroundJobs; namespace Volo.Abp.BackgroundJobs;
public class DynamicJobExecutionTracker public class DynamicJobExecutionTracker
{ {
public List<string> ExecutedJsonData { get; } = new(); public ConcurrentBag<string> ExecutedJsonData { get; } = new();
} }

Loading…
Cancel
Save