Browse Source

Merge pull request #25397 from abpframework/salihozkara/dynamic-worker-capabilities

Expose dynamic background worker scheduler capabilities
pull/25416/head
Ma Liming 5 months ago
committed by GitHub
parent
commit
966c3878f7
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 6
      framework/src/Volo.Abp.BackgroundWorkers.Hangfire/Volo/Abp/BackgroundWorkers/Hangfire/HangfireDynamicBackgroundWorkerManager.cs
  2. 6
      framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/QuartzDynamicBackgroundWorkerManager.cs
  3. 17
      framework/src/Volo.Abp.BackgroundWorkers/Volo/Abp/BackgroundWorkers/DefaultDynamicBackgroundWorkerManager.cs
  4. 6
      framework/src/Volo.Abp.BackgroundWorkers/Volo/Abp/BackgroundWorkers/IDynamicBackgroundWorkerManager.cs
  5. 8
      framework/src/Volo.Abp.BackgroundWorkers/Volo/Abp/BackgroundWorkers/ISupportsCronScheduling.cs
  6. 8
      framework/src/Volo.Abp.BackgroundWorkers/Volo/Abp/BackgroundWorkers/ISupportsRuntimeRegistration.cs
  7. 51
      framework/test/Volo.Abp.BackgroundJobs.Tests/Volo/Abp/BackgroundWorkers/DynamicBackgroundWorkerManager_Tests.cs

6
framework/src/Volo.Abp.BackgroundWorkers.Hangfire/Volo/Abp/BackgroundWorkers/Hangfire/HangfireDynamicBackgroundWorkerManager.cs

@ -13,7 +13,11 @@ using Volo.Abp.Hangfire;
namespace Volo.Abp.BackgroundWorkers.Hangfire;
[Dependency(ReplaceServices = true)]
public class HangfireDynamicBackgroundWorkerManager : IDynamicBackgroundWorkerManager, ISingletonDependency
public class HangfireDynamicBackgroundWorkerManager :
IDynamicBackgroundWorkerManager,
ISupportsRuntimeRegistration,
ISupportsCronScheduling,
ISingletonDependency
{
protected IServiceProvider ServiceProvider { get; }
protected IDynamicBackgroundWorkerHandlerRegistry HandlerRegistry { get; }

6
framework/src/Volo.Abp.BackgroundWorkers.Quartz/Volo/Abp/BackgroundWorkers/Quartz/QuartzDynamicBackgroundWorkerManager.cs

@ -10,7 +10,11 @@ using Volo.Abp.DependencyInjection;
namespace Volo.Abp.BackgroundWorkers.Quartz;
[Dependency(ReplaceServices = true)]
public class QuartzDynamicBackgroundWorkerManager : IDynamicBackgroundWorkerManager, ISingletonDependency
public class QuartzDynamicBackgroundWorkerManager :
IDynamicBackgroundWorkerManager,
ISupportsRuntimeRegistration,
ISupportsCronScheduling,
ISingletonDependency
{
public const string DynamicWorkerNameKey = "AbpDynamicWorkerName";

17
framework/src/Volo.Abp.BackgroundWorkers/Volo/Abp/BackgroundWorkers/DefaultDynamicBackgroundWorkerManager.cs

@ -10,7 +10,10 @@ using Volo.Abp.Threading;
namespace Volo.Abp.BackgroundWorkers;
public class DefaultDynamicBackgroundWorkerManager : IDynamicBackgroundWorkerManager, ISingletonDependency
public class DefaultDynamicBackgroundWorkerManager :
IDynamicBackgroundWorkerManager,
ISupportsRuntimeRegistration,
ISingletonDependency
{
protected IServiceProvider ServiceProvider { get; }
public ILogger<DefaultDynamicBackgroundWorkerManager> Logger { get; set; }
@ -39,11 +42,11 @@ public class DefaultDynamicBackgroundWorkerManager : IDynamicBackgroundWorkerMan
schedule.Validate();
if (schedule.Period == null)
if (!schedule.CronExpression.IsNullOrWhiteSpace())
{
throw new AbpException(
$"The default in-memory background worker manager does not support CronExpression without Period for dynamic worker '{workerName}'. " +
"Please set Period, or use a scheduler-backed provider (Hangfire, Quartz, TickerQ).");
$"The default in-memory background worker manager does not support CronExpression for dynamic worker '{workerName}'. " +
"Please clear CronExpression and use Period-based scheduling, or use a scheduler-backed provider (Hangfire or Quartz).");
}
await _semaphore.WaitAsync(cancellationToken);
@ -102,11 +105,11 @@ public class DefaultDynamicBackgroundWorkerManager : IDynamicBackgroundWorkerMan
schedule.Validate();
if (schedule.Period == null)
if (!schedule.CronExpression.IsNullOrWhiteSpace())
{
throw new AbpException(
$"The default in-memory background worker manager does not support CronExpression without Period for dynamic worker '{workerName}'. " +
"Please set Period, or use a scheduler-backed provider (Hangfire, Quartz, TickerQ).");
$"The default in-memory background worker manager does not support CronExpression for dynamic worker '{workerName}'. " +
"Please clear CronExpression and use Period-based scheduling, or use a scheduler-backed provider (Hangfire or Quartz).");
}
await _semaphore.WaitAsync(cancellationToken);

6
framework/src/Volo.Abp.BackgroundWorkers/Volo/Abp/BackgroundWorkers/IDynamicBackgroundWorkerManager.cs

@ -6,6 +6,12 @@ namespace Volo.Abp.BackgroundWorkers;
/// <summary>
/// Manages dynamic background workers that are registered at runtime
/// without requiring a strongly-typed worker class.
/// <para>
/// Implementations may differ in capabilities. Check <see cref="ISupportsRuntimeRegistration"/>
/// before calling <see cref="AddAsync"/> / <see cref="RemoveAsync"/> / <see cref="UpdateScheduleAsync"/>,
/// and <see cref="ISupportsCronScheduling"/> before passing
/// <see cref="DynamicBackgroundWorkerSchedule.CronExpression"/>.
/// </para>
/// </summary>
public interface IDynamicBackgroundWorkerManager
{

8
framework/src/Volo.Abp.BackgroundWorkers/Volo/Abp/BackgroundWorkers/ISupportsCronScheduling.cs

@ -0,0 +1,8 @@
namespace Volo.Abp.BackgroundWorkers;
/// <summary>
/// Marks a dynamic background worker manager that supports cron-based scheduling.
/// </summary>
public interface ISupportsCronScheduling
{
}

8
framework/src/Volo.Abp.BackgroundWorkers/Volo/Abp/BackgroundWorkers/ISupportsRuntimeRegistration.cs

@ -0,0 +1,8 @@
namespace Volo.Abp.BackgroundWorkers;
/// <summary>
/// Marks a dynamic background worker manager that supports registering workers at runtime.
/// </summary>
public interface ISupportsRuntimeRegistration
{
}

51
framework/test/Volo.Abp.BackgroundJobs.Tests/Volo/Abp/BackgroundWorkers/DynamicBackgroundWorkerManager_Tests.cs

@ -5,6 +5,7 @@ using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Shouldly;
using Volo.Abp;
using Volo.Abp.BackgroundJobs;
using Volo.Abp.BackgroundWorkers;
using Xunit;
@ -20,6 +21,13 @@ public class DynamicBackgroundWorkerManager_Tests : BackgroundJobsTestBase
_dynamicWorkerManager = GetRequiredService<IDynamicBackgroundWorkerManager>();
}
[Fact]
public void Should_Report_Provider_Capabilities_Using_Marker_Interfaces()
{
(_dynamicWorkerManager is ISupportsRuntimeRegistration).ShouldBeTrue();
(_dynamicWorkerManager is ISupportsCronScheduling).ShouldBeFalse();
}
[Fact]
public async Task Should_Register_Dynamic_Worker()
{
@ -235,6 +243,49 @@ public class DynamicBackgroundWorkerManager_Tests : BackgroundJobsTestBase
});
}
[Fact]
public async Task Should_Throw_When_CronExpression_Is_Set()
{
var workerName = "dynamic-worker-" + Guid.NewGuid();
await Assert.ThrowsAsync<AbpException>(async () =>
{
await _dynamicWorkerManager.AddAsync(
workerName,
new DynamicBackgroundWorkerSchedule
{
Period = 1000,
CronExpression = "0 */5 * * * *"
},
(_, _) => Task.CompletedTask
);
});
}
[Fact]
public async Task Should_Throw_When_CronExpression_Is_Set_On_UpdateSchedule()
{
var workerName = "dynamic-worker-" + Guid.NewGuid();
await _dynamicWorkerManager.AddAsync(
workerName,
new DynamicBackgroundWorkerSchedule { Period = 1000 },
(_, _) => Task.CompletedTask
);
await Assert.ThrowsAsync<AbpException>(async () =>
{
await _dynamicWorkerManager.UpdateScheduleAsync(
workerName,
new DynamicBackgroundWorkerSchedule
{
Period = 1000,
CronExpression = "0 */5 * * * *"
}
);
});
}
[Fact]
public async Task Should_Continue_Running_After_Handler_Throws_Exception()
{

Loading…
Cancel
Save