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.Collections.Concurrent;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
@ -11,7 +12,7 @@ namespace Volo.Abp.BackgroundJobs;
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 IDynamicBackgroundJobHandlerRegistry HandlerRegistry { get; }
@ -83,9 +84,8 @@ public class DefaultDynamicBackgroundJobManager : IDynamicBackgroundJobManager,
var json = JsonSerializer.Serialize(args);
var typedArgs = JsonSerializer.Deserialize(argsType, json);
var enqueueMethod = GetOrCreateEnqueueMethod(argsType);
var task = (Task<string>)enqueueMethod.Invoke(BackgroundJobManager, [typedArgs, priority, delay])!;
return await task;
var enqueueDelegate = GetOrCreateEnqueueDelegate(argsType);
return await enqueueDelegate(BackgroundJobManager, typedArgs, priority, delay);
}
protected virtual Task<string> EnqueueDynamicHandlerJobAsync(
@ -99,15 +99,39 @@ public class DefaultDynamicBackgroundJobManager : IDynamicBackgroundJobManager,
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)
.GetMethods(BindingFlags.Public | BindingFlags.Instance)
.Single(m => m.Name == nameof(IBackgroundJobManager.EnqueueAsync) && m.IsGenericMethodDefinition);
return method.MakeGenericMethod(type);
.FirstOrDefault(m => m.Name == nameof(IBackgroundJobManager.EnqueueAsync)
&& m.IsGenericMethodDefinition
&& 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)
{
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]
public async Task Should_Execute_Dynamic_Handler_Job()
{
_tracker.ExecutedJsonData.ShouldBeEmpty();
_tracker.ExecutedJsonData.IsEmpty.ShouldBeTrue();
await _backgroundJobExecuter.ExecuteAsync(
new JobExecutionContext(
@ -100,13 +100,20 @@ public class BackgroundJobManager_Tests : BackgroundJobsTestBase
var typedJobName = BackgroundJobNameAttribute.GetName<MyJobArgs>();
_dynamicBackgroundJobManager.RegisterHandler(typedJobName, (_, _) => Task.CompletedTask);
var jobIdAsString = await _dynamicBackgroundJobManager.EnqueueAsync(typedJobName, new { Value = "42" });
jobIdAsString.ShouldNotBe(default);
var jobInfo = await _backgroundJobStore.FindAsync(Guid.Parse(jobIdAsString));
jobInfo.ShouldNotBeNull();
jobInfo.JobName.ShouldBe(typedJobName);
jobInfo.JobName.ShouldNotBe(DynamicBackgroundJobArgs.JobNameConstant);
try
{
var jobIdAsString = await _dynamicBackgroundJobManager.EnqueueAsync(typedJobName, new { Value = "42" });
jobIdAsString.ShouldNotBe(default);
var jobInfo = await _backgroundJobStore.FindAsync(Guid.Parse(jobIdAsString));
jobInfo.ShouldNotBeNull();
jobInfo.JobName.ShouldBe(typedJobName);
jobInfo.JobName.ShouldNotBe(DynamicBackgroundJobArgs.JobNameConstant);
}
finally
{
_dynamicBackgroundJobManager.UnregisterHandler(typedJobName);
}
}
[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;
public class DynamicJobExecutionTracker
{
public List<string> ExecutedJsonData { get; } = new();
public ConcurrentBag<string> ExecutedJsonData { get; } = new();
}

Loading…
Cancel
Save