Browse Source

Refactor TickerQ managers and add worker configuration support

pull/23802/head
maliming 4 months ago
parent
commit
14c54c4302
No known key found for this signature in database GPG Key ID: A646B9CB645ECEA4
  1. 81
      docs/en/framework/infrastructure/background-jobs/tickerq.md
  2. 100
      docs/en/framework/infrastructure/background-workers/tickerq.md
  3. 2
      framework/src/Volo.Abp.BackgroundJobs.TickerQ/Volo/Abp/BackgroundJobs/TickerQ/AbpBackgroundJobsTickerQModule.cs
  4. 20
      framework/src/Volo.Abp.BackgroundJobs.TickerQ/Volo/Abp/BackgroundJobs/TickerQ/AbpBackgroundJobsTickerQOptions.cs
  5. 5
      framework/src/Volo.Abp.BackgroundJobs.TickerQ/Volo/Abp/BackgroundJobs/TickerQ/AbpBackgroundJobsTimeTickerConfiguration.cs
  6. 23
      framework/src/Volo.Abp.BackgroundJobs.TickerQ/Volo/Abp/BackgroundJobs/TickerQ/AbpTickerQBackgroundJobManager.cs
  7. 12
      framework/src/Volo.Abp.BackgroundWorkers.TickerQ/Volo/Abp/BackgroundWorkers/TickerQ/AbpBackgroundWorkersCronTickerConfiguration.cs
  8. 35
      framework/src/Volo.Abp.BackgroundWorkers.TickerQ/Volo/Abp/BackgroundWorkers/TickerQ/AbpBackgroundWorkersTickerQModule.cs
  9. 34
      framework/src/Volo.Abp.BackgroundWorkers.TickerQ/Volo/Abp/BackgroundWorkers/TickerQ/AbpBackgroundWorkersTickerQOptions.cs
  10. 28
      framework/src/Volo.Abp.BackgroundWorkers.TickerQ/Volo/Abp/BackgroundWorkers/TickerQ/AbpTickerQBackgroundWorkerManager.cs
  11. 14
      framework/src/Volo.Abp.BackgroundWorkers.TickerQ/Volo/Abp/BackgroundWorkers/TickerQ/AbpTickerQBackgroundWorkersProvider.cs
  12. 12
      framework/src/Volo.Abp.BackgroundWorkers.TickerQ/Volo/Abp/BackgroundWorkers/TickerQ/AbpTickerQCronBackgroundWorker.cs
  13. 4
      framework/src/Volo.Abp.BackgroundWorkers.TickerQ/Volo/Abp/BackgroundWorkers/TickerQ/AbpTickerQPeriodicBackgroundWorkerInvoker.cs
  14. 15
      modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.TickerQ/CleanupJobs.cs
  15. 56
      modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.TickerQ/DemoAppTickerQModule.cs

81
docs/en/framework/infrastructure/background-jobs/tickerq.md

@ -42,6 +42,31 @@ public class YourModule : AbpModule
## Configuration
### AddTickerQ
You can call the `AddTickerQ` extension method in the `ConfigureServices` method of your module to configure TickerQ services:
> This is optional. ABP will automatically register TickerQ services.
```csharp
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddTickerQ(x =>
{
// Configure TickerQ options here
});
}
```
### UseAbpTickerQ
You need to call the `UseAbpTickerQ` extension method instead of `AddTickerQ` in the `OnApplicationInitialization` method of your module:
```csharp
// (default: TickerQStartMode.Immediate)
app.UseAbpTickerQ(startMode: ...);
```
### AbpBackgroundJobsTickerQOptions
You can configure the `TimeTicker` properties for specific jobs. For example, Change `Priority`, `Retries` and `RetryIntervals` properties:
@ -49,14 +74,18 @@ You can configure the `TimeTicker` properties for specific jobs. For example, Ch
```csharp
Configure<AbpBackgroundJobsTickerQOptions>(options =>
{
options.AddJobConfiguration<MyJob>(new AbpBackgroundJobsTimeTickerConfiguration()
options.AddJobConfiguration<MyBackgroundJob>(new AbpBackgroundJobsTimeTickerConfiguration()
{
Retries = 3,
RetryIntervals = new[] {30, 60, 120}, // Retry after 30s, 60s, then 2min
Priority = TickerTaskPriority.High
// Optional batching
//BatchParent = Guid.Parse("...."),
//BatchRunCondition = BatchRunCondition.OnSuccess
});
options.AddJobConfiguration<MyJob2>(new AbpBackgroundJobsTimeTickerConfiguration()
options.AddJobConfiguration<MyBackgroundJob2>(new AbpBackgroundJobsTimeTickerConfiguration()
{
Retries = 5,
RetryIntervals = new[] {30, 60, 120}, // Retry after 30s, 60s, then 2min
@ -65,6 +94,54 @@ Configure<AbpBackgroundJobsTickerQOptions>(options =>
});
```
### Add your own TickerQ Background Jobs Definitions
ABP will handle the TickerQ job definitions by `AbpTickerQFunctionProvider` service. You shouldn't use `TickerFunction` to add your own job definitions. You can inject and use the `AbpTickerQFunctionProvider` to add your own definitions and use `ITimeTickerManager<TimeTicker>` or `ICronTickerManager<CronTicker>` to manage the jobs.
For example, you can add a `CleanupJobs` job definition in the `OnPreApplicationInitializationAsync` method of your module:
```csharp
public class CleanupJobs
{
public async Task CleanupLogsAsync(TickerFunctionContext<string> tickerContext, CancellationToken cancellationToken)
{
var logFileName = tickerContext.Request;
Console.WriteLine($"Cleaning up log file: {logFileName} at {DateTime.Now}");
}
}
```
```csharp
public override Task OnPreApplicationInitializationAsync(ApplicationInitializationContext context)
{
var abpTickerQFunctionProvider = context.ServiceProvider.GetRequiredService<AbpTickerQFunctionProvider>();
abpTickerQFunctionProvider.Functions.TryAdd(nameof(CleanupJobs), (string.Empty, TickerTaskPriority.Normal, new TickerFunctionDelegate(async (cancellationToken, serviceProvider, tickerFunctionContext) =>
{
var service = new CleanupJobs(); // Or get it from the serviceProvider
var request = await TickerRequestProvider.GetRequestAsync<string>(serviceProvider, tickerFunctionContext.Id, tickerFunctionContext.Type);
var genericContext = new TickerFunctionContext<string>(tickerFunctionContext, request);
await service.CleanupLogsAsync(genericContext, cancellationToken);
})));
abpTickerQFunctionProvider.RequestTypes.TryAdd(nameof(CleanupJobs), (typeof(string).FullName, typeof(string)));
return Task.CompletedTask;
}
```
And then you can add a job by using the `ITimeTickerManager<TimeTicker>`:
```csharp
var timeTickerManager = context.ServiceProvider.GetRequiredService<ITimeTickerManager<TimeTicker>>();
await timeTickerManager.AddAsync(new TimeTicker
{
Function = nameof(CleanupJobs),
ExecutionTime = DateTime.UtcNow.AddSeconds(5),
Request = TickerHelper.CreateTickerRequest<string>("cleanup_example_file.txt"),
Retries = 3,
RetryIntervals = new[] { 30, 60, 120 }, // Retry after 30s, 60s, then 2min
});
```
### TickerQ Dashboard and EF Core Integration
You can install the [TickerQ dashboard](https://tickerq.net/setup/dashboard.html) and [Entity Framework Core](https://tickerq.net/setup/tickerq-ef-core.html) integration by its documentation. There is no specific configuration needed for the ABP integration.

100
docs/en/framework/infrastructure/background-workers/tickerq.md

@ -40,4 +40,102 @@ public class YourModule : AbpModule
## Configuration
TODO:
### AddTickerQ
You can call the `AddTickerQ` extension method in the `ConfigureServices` method of your module to configure TickerQ services:
> This is optional. ABP will automatically register TickerQ services.
```csharp
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddTickerQ(x =>
{
// Configure TickerQ options here
});
}
```
### UseAbpTickerQ
You need to call the `UseAbpTickerQ` extension method instead of `AddTickerQ` in the `OnApplicationInitialization` method of your module:
```csharp
// (default: TickerQStartMode.Immediate)
app.UseAbpTickerQ(startMode: ...);
```
### AbpBackgroundWorkersTickerQOptions
You can configure the `CronTicker` properties for specific jobs. For example, Change `Priority`, `Retries` and `RetryIntervals` properties:
```csharp
Configure<AbpBackgroundWorkersTickerQOptions>(options =>
{
options.AddConfiguration<MyBackgroundWorker>(new AbpBackgroundWorkersCronTickerConfiguration()
{
Retries = 3,
RetryIntervals = new[] {30, 60, 120}, // Retry after 30s, 60s, then 2min,
Priority = TickerTaskPriority.High
});
});
```
### Add your own TickerQ Background Worker Definitions
ABP will handle the TickerQ job definitions by `AbpTickerQFunctionProvider` service. You shouldn't use `TickerFunction` to add your own job definitions. You can inject and use the `AbpTickerQFunctionProvider` to add your own definitions and use `ITimeTickerManager<TimeTicker>` or `ICronTickerManager<CronTicker>` to manage the jobs.
For example, you can add a `CleanupJobs` job definition in the `OnPreApplicationInitializationAsync` method of your module:
```csharp
public class CleanupJobs
{
public async Task CleanupLogsAsync(TickerFunctionContext<string> tickerContext, CancellationToken cancellationToken)
{
var logFileName = tickerContext.Request;
Console.WriteLine($"Cleaning up log file: {logFileName} at {DateTime.Now}");
}
}
```
```csharp
public override Task OnPreApplicationInitializationAsync(ApplicationInitializationContext context)
{
var abpTickerQFunctionProvider = context.ServiceProvider.GetRequiredService<AbpTickerQFunctionProvider>();
abpTickerQFunctionProvider.Functions.TryAdd(nameof(CleanupJobs), (string.Empty, TickerTaskPriority.Normal, new TickerFunctionDelegate(async (cancellationToken, serviceProvider, tickerFunctionContext) =>
{
var service = new CleanupJobs(); // Or get it from the serviceProvider
var request = await TickerRequestProvider.GetRequestAsync<string>(serviceProvider, tickerFunctionContext.Id, tickerFunctionContext.Type);
var genericContext = new TickerFunctionContext<string>(tickerFunctionContext, request);
await service.CleanupLogsAsync(genericContext, cancellationToken);
})));
abpTickerQFunctionProvider.RequestTypes.TryAdd(nameof(CleanupJobs), (typeof(string).FullName, typeof(string)));
return Task.CompletedTask;
}
```
And then you can add a job by using the `ICronTickerManager<CronTicker>`:
```csharp
var cronTickerManager = context.ServiceProvider.GetRequiredService<ICronTickerManager<CronTicker>>();
await cronTickerManager.AddAsync(new CronTicker
{
Function = nameof(CleanupJobs),
Expression = "0 */6 * * *", // Every 6 hours
Request = TickerHelper.CreateTickerRequest<string>("cleanup_example_file.txt"),
Retries = 2,
RetryIntervals = new[] { 60, 300 }
});
```
You can specify a cron expression instead of use `ICronTickerManager<CronTicker>` to add a worker:
```csharp
abpTickerQFunctionProvider.Functions.TryAdd(nameof(CleanupJobs), (string.Empty, TickerTaskPriority.Normal, new TickerFunctionDelegate(async (cancellationToken, serviceProvider, tickerFunctionContext) =>
{
var service = new CleanupJobs();
var request = await TickerRequestProvider.GetRequestAsync<string>(serviceProvider, tickerFunctionContext.Id, tickerFunctionContext.Type);
var genericContext = new TickerFunctionContext<string>(tickerFunctionContext, request);
await service.CleanupLogsAsync(genericContext, cancellationToken);
})));
```

2
framework/src/Volo.Abp.BackgroundJobs.TickerQ/Volo/Abp/BackgroundJobs/TickerQ/AbpBackgroundJobsTickerQModule.cs

@ -26,7 +26,7 @@ public class AbpBackgroundJobsTickerQModule : AbpModule
{
var genericMethod = GetTickerFunctionDelegateMethod.MakeGenericMethod(jobConfiguration.ArgsType);
var tickerFunctionDelegate = (TickerFunctionDelegate)genericMethod.Invoke(null, [jobConfiguration.ArgsType])!;
var config = abpBackgroundJobsTickerQOptions.Value.GetJobConfigurationOrNull(jobConfiguration.JobType);
var config = abpBackgroundJobsTickerQOptions.Value.GetConfigurationOrNull(jobConfiguration.JobType);
tickerFunctionDelegates.TryAdd(jobConfiguration.JobName, (string.Empty, config?.Priority ?? TickerTaskPriority.Normal, tickerFunctionDelegate));
requestTypes.TryAdd(jobConfiguration.JobName, (jobConfiguration.ArgsType.FullName, jobConfiguration.ArgsType)!);
}

20
framework/src/Volo.Abp.BackgroundJobs.TickerQ/Volo/Abp/BackgroundJobs/TickerQ/AbpBackgroundJobsTickerQOptions.cs

@ -5,30 +5,30 @@ namespace Volo.Abp.BackgroundJobs.TickerQ;
public class AbpBackgroundJobsTickerQOptions
{
private readonly Dictionary<Type, AbpBackgroundJobsTimeTickerConfiguration> _jobConfigurations;
private readonly Dictionary<Type, AbpBackgroundJobsTimeTickerConfiguration> _configurations;
public AbpBackgroundJobsTickerQOptions()
{
_jobConfigurations = new Dictionary<Type, AbpBackgroundJobsTimeTickerConfiguration>();
_configurations = new Dictionary<Type, AbpBackgroundJobsTimeTickerConfiguration>();
}
public void AddJobConfiguration<TJob>(AbpBackgroundJobsTimeTickerConfiguration configuration)
public void AddConfiguration<TJob>(AbpBackgroundJobsTimeTickerConfiguration configuration)
{
AddJobConfiguration(typeof(TJob), configuration);
AddConfiguration(typeof(TJob), configuration);
}
public void AddJobConfiguration(Type jobType, AbpBackgroundJobsTimeTickerConfiguration configuration)
public void AddConfiguration(Type jobType, AbpBackgroundJobsTimeTickerConfiguration configuration)
{
_jobConfigurations[jobType] = configuration;
_configurations[jobType] = configuration;
}
public AbpBackgroundJobsTimeTickerConfiguration? GetJobConfigurationOrNull<TJob>()
public AbpBackgroundJobsTimeTickerConfiguration? GetConfigurationOrNull<TJob>()
{
return GetJobConfigurationOrNull(typeof(TJob));
return GetConfigurationOrNull(typeof(TJob));
}
public AbpBackgroundJobsTimeTickerConfiguration? GetJobConfigurationOrNull(Type jobType)
public AbpBackgroundJobsTimeTickerConfiguration? GetConfigurationOrNull(Type jobType)
{
return _jobConfigurations.GetValueOrDefault(jobType);
return _configurations.GetValueOrDefault(jobType);
}
}

5
framework/src/Volo.Abp.BackgroundJobs.TickerQ/Volo/Abp/BackgroundJobs/TickerQ/AbpBackgroundJobsTimeTickerConfiguration.cs

@ -1,3 +1,4 @@
using System;
using TickerQ.Utilities.Enums;
namespace Volo.Abp.BackgroundJobs.TickerQ;
@ -9,4 +10,8 @@ public class AbpBackgroundJobsTimeTickerConfiguration
public int[]? RetryIntervals { get; set; }
public TickerTaskPriority? Priority { get; set; }
public Guid? BatchParent { get; set; }
public BatchRunCondition? BatchRunCondition { get; set; }
}

23
framework/src/Volo.Abp.BackgroundJobs.TickerQ/Volo/Abp/BackgroundJobs/TickerQ/TickerQBackgroundJobManager.cs → framework/src/Volo.Abp.BackgroundJobs.TickerQ/Volo/Abp/BackgroundJobs/TickerQ/AbpTickerQBackgroundJobManager.cs

@ -1,5 +1,7 @@
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using TickerQ.Utilities;
using TickerQ.Utilities.Interfaces.Managers;
@ -9,17 +11,21 @@ using Volo.Abp.DependencyInjection;
namespace Volo.Abp.BackgroundJobs.TickerQ;
[Dependency(ReplaceServices = true)]
public class TickerQBackgroundJobManager : IBackgroundJobManager, ITransientDependency
public class AbpTickerQBackgroundJobManager : IBackgroundJobManager, ITransientDependency
{
public ILogger<AbpTickerQBackgroundJobManager> Logger { get; set; }
protected ITimeTickerManager<TimeTicker> TimeTickerManager { get; }
protected AbpBackgroundJobOptions Options { get; }
protected AbpBackgroundJobsTickerQOptions TickerQOptions { get; }
public TickerQBackgroundJobManager(
public AbpTickerQBackgroundJobManager(
ITimeTickerManager<TimeTicker> timeTickerManager,
IOptions<AbpBackgroundJobOptions> options,
IOptions<AbpBackgroundJobsTickerQOptions> tickerQOptions)
{
Logger = NullLogger<AbpTickerQBackgroundJobManager>.Instance;
TimeTickerManager = timeTickerManager;
Options = options.Value;
TickerQOptions = tickerQOptions.Value;
@ -36,14 +42,23 @@ public class TickerQBackgroundJobManager : IBackgroundJobManager, ITransientDepe
Request = TickerHelper.CreateTickerRequest<TArgs>(args),
};
var config = TickerQOptions.GetJobConfigurationOrNull(job.JobType);
var config = TickerQOptions.GetConfigurationOrNull(job.JobType);
if (config != null)
{
timeTicker.Retries = config.Retries ?? timeTicker.Retries;
timeTicker.RetryIntervals = config.RetryIntervals ?? timeTicker.RetryIntervals;
timeTicker.BatchParent = config.BatchParent ?? timeTicker.BatchParent;
timeTicker.BatchRunCondition = config.BatchRunCondition ?? timeTicker.BatchRunCondition;
}
var result = await TimeTickerManager.AddAsync(timeTicker);
return !result.IsSucceded ? throw result.Exception : result.Result.Id.ToString();
if (!result.IsSucceded)
{
Logger.LogException(result.Exception);
return timeTicker.Id.ToString();
}
return result.Result.Id.ToString();
}
}

12
framework/src/Volo.Abp.BackgroundWorkers.TickerQ/Volo/Abp/BackgroundWorkers/TickerQ/AbpBackgroundWorkersCronTickerConfiguration.cs

@ -0,0 +1,12 @@
using TickerQ.Utilities.Enums;
namespace Volo.Abp.BackgroundWorkers.TickerQ;
public class AbpBackgroundWorkersCronTickerConfiguration
{
public int? Retries { get; set; }
public int[]? RetryIntervals { get; set; }
public TickerTaskPriority? Priority { get; set; }
}

35
framework/src/Volo.Abp.BackgroundWorkers.TickerQ/Volo/Abp/BackgroundWorkers/TickerQ/AbpBackgroundWorkersTickerQModule.cs

@ -1,4 +1,10 @@
using Volo.Abp.Modularity;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using TickerQ.Utilities.Interfaces.Managers;
using TickerQ.Utilities.Models.Ticker;
using Volo.Abp.Modularity;
using Volo.Abp.TickerQ;
namespace Volo.Abp.BackgroundWorkers.TickerQ;
@ -6,5 +12,32 @@ namespace Volo.Abp.BackgroundWorkers.TickerQ;
[DependsOn(typeof(AbpBackgroundWorkersModule), typeof(AbpTickerQModule))]
public class AbpBackgroundWorkersTickerQModule : AbpModule
{
public override async Task OnPostApplicationInitializationAsync(ApplicationInitializationContext context)
{
var abpTickerQBackgroundWorkersProvider = context.ServiceProvider.GetRequiredService<AbpTickerQBackgroundWorkersProvider>();
var cronTickerManager = context.ServiceProvider.GetRequiredService<ICronTickerManager<CronTicker>>();
var abpBackgroundWorkersTickerQOptions = context.ServiceProvider.GetRequiredService<IOptions<AbpBackgroundWorkersTickerQOptions>>().Value;
foreach (var backgroundWorker in abpTickerQBackgroundWorkersProvider.BackgroundWorkers)
{
var cronTicker = new CronTicker
{
Function = backgroundWorker.Value.Function,
Expression = backgroundWorker.Value.CronExpression
};
var config = abpBackgroundWorkersTickerQOptions.GetConfigurationOrNull(backgroundWorker.Value.WorkerType);
if (config != null)
{
cronTicker.Retries = config.Retries ?? cronTicker.Retries;
cronTicker.RetryIntervals = config.RetryIntervals ?? cronTicker.RetryIntervals;
}
var result = await cronTickerManager.AddAsync(cronTicker);
if (!result.IsSucceded)
{
var logger = context.ServiceProvider.GetRequiredService<ILogger<AbpBackgroundWorkersTickerQModule>>();
logger.LogException(result.Exception);
}
}
}
}

34
framework/src/Volo.Abp.BackgroundWorkers.TickerQ/Volo/Abp/BackgroundWorkers/TickerQ/AbpBackgroundWorkersTickerQOptions.cs

@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
namespace Volo.Abp.BackgroundWorkers.TickerQ;
public class AbpBackgroundWorkersTickerQOptions
{
private readonly Dictionary<Type, AbpBackgroundWorkersCronTickerConfiguration> _onfigurations;
public AbpBackgroundWorkersTickerQOptions()
{
_onfigurations = new Dictionary<Type, AbpBackgroundWorkersCronTickerConfiguration>();
}
public void AddConfiguration<TJob>(AbpBackgroundWorkersCronTickerConfiguration configuration)
{
AddConfiguration(typeof(TJob), configuration);
}
public void AddConfiguration(Type jobType, AbpBackgroundWorkersCronTickerConfiguration configuration)
{
_onfigurations[jobType] = configuration;
}
public AbpBackgroundWorkersCronTickerConfiguration? GetConfigurationOrNull<TJob>()
{
return GetConfigurationOrNull(typeof(TJob));
}
public AbpBackgroundWorkersCronTickerConfiguration? GetConfigurationOrNull(Type jobType)
{
return _onfigurations.GetValueOrDefault(jobType);
}
}

28
framework/src/Volo.Abp.BackgroundWorkers.TickerQ/Volo/Abp/BackgroundWorkers/TickerQ/TickerQBackgroundWorkerManager.cs → framework/src/Volo.Abp.BackgroundWorkers.TickerQ/Volo/Abp/BackgroundWorkers/TickerQ/AbpTickerQBackgroundWorkerManager.cs

@ -1,21 +1,30 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using TickerQ.Utilities.Enums;
using Volo.Abp.DependencyInjection;
using Volo.Abp.DynamicProxy;
using Volo.Abp.TickerQ;
namespace Volo.Abp.BackgroundWorkers.TickerQ;
[Dependency(ReplaceServices = true)]
[ExposeServices(typeof(IBackgroundWorkerManager), typeof(TickerQBackgroundWorkerManager))]
public class TickerQBackgroundWorkerManager : BackgroundWorkerManager, ISingletonDependency
[ExposeServices(typeof(IBackgroundWorkerManager), typeof(AbpTickerQBackgroundWorkerManager))]
public class AbpTickerQBackgroundWorkerManager : BackgroundWorkerManager, ISingletonDependency
{
protected AbpTickerQFunctionProvider AbpTickerQFunctionProvider { get; }
protected AbpTickerQBackgroundWorkersProvider AbpTickerQBackgroundWorkersProvider { get; }
protected AbpBackgroundWorkersTickerQOptions Options { get; }
public TickerQBackgroundWorkerManager(AbpTickerQFunctionProvider abpTickerQFunctionProvider)
public AbpTickerQBackgroundWorkerManager(
AbpTickerQFunctionProvider abpTickerQFunctionProvider,
AbpTickerQBackgroundWorkersProvider abpTickerQBackgroundWorkersProvider,
IOptions<AbpBackgroundWorkersTickerQOptions> options)
{
AbpTickerQFunctionProvider = abpTickerQFunctionProvider;
AbpTickerQBackgroundWorkersProvider = abpTickerQBackgroundWorkersProvider;
Options = options.Value;
}
public override async Task AddAsync(IBackgroundWorker worker, CancellationToken cancellationToken = default)
@ -43,11 +52,20 @@ public class TickerQBackgroundWorkerManager : BackgroundWorkerManager, ISingleto
cronExpression = cronExpression ?? GetCron(period!.Value);
var name = BackgroundWorkerNameAttribute.GetNameOrNull(worker.GetType()) ?? worker.GetType().FullName;
AbpTickerQFunctionProvider.Functions.TryAdd(name!, (cronExpression!, TickerTaskPriority.LongRunning, async (tickerQCancellationToken, serviceProvider, tickerFunctionContext) =>
var config = Options.GetConfigurationOrNull(ProxyHelper.GetUnProxiedType(worker));
AbpTickerQFunctionProvider.Functions.TryAdd(name!, (string.Empty, config?.Priority ?? TickerTaskPriority.LongRunning, async (tickerQCancellationToken, serviceProvider, tickerFunctionContext) =>
{
var workerInvoker = new TickerQPeriodicBackgroundWorkerInvoker(worker, serviceProvider);
var workerInvoker = new AbpTickerQPeriodicBackgroundWorkerInvoker(worker, serviceProvider);
await workerInvoker.DoWorkAsync(tickerFunctionContext, tickerQCancellationToken);
}));
AbpTickerQBackgroundWorkersProvider.BackgroundWorkers.Add(name!, new AbpTickerQCronBackgroundWorker
{
Function = name!,
CronExpression = cronExpression,
WorkerType = ProxyHelper.GetUnProxiedType(worker)
});
}
await base.AddAsync(worker, cancellationToken);

14
framework/src/Volo.Abp.BackgroundWorkers.TickerQ/Volo/Abp/BackgroundWorkers/TickerQ/AbpTickerQBackgroundWorkersProvider.cs

@ -0,0 +1,14 @@
using System.Collections.Generic;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.BackgroundWorkers.TickerQ;
public class AbpTickerQBackgroundWorkersProvider : ISingletonDependency
{
public Dictionary<string, AbpTickerQCronBackgroundWorker> BackgroundWorkers { get;}
public AbpTickerQBackgroundWorkersProvider()
{
BackgroundWorkers = new Dictionary<string, AbpTickerQCronBackgroundWorker>();
}
}

12
framework/src/Volo.Abp.BackgroundWorkers.TickerQ/Volo/Abp/BackgroundWorkers/TickerQ/AbpTickerQCronBackgroundWorker.cs

@ -0,0 +1,12 @@
using System;
namespace Volo.Abp.BackgroundWorkers.TickerQ;
public class AbpTickerQCronBackgroundWorker
{
public string Function { get; set; } = null!;
public string CronExpression { get; set; } = null!;
public Type WorkerType { get; set; } = null!;
}

4
framework/src/Volo.Abp.BackgroundWorkers.TickerQ/Volo/Abp/BackgroundWorkers/TickerQ/TickerQPeriodicBackgroundWorkerInvoker.cs → framework/src/Volo.Abp.BackgroundWorkers.TickerQ/Volo/Abp/BackgroundWorkers/TickerQ/AbpTickerQPeriodicBackgroundWorkerInvoker.cs

@ -7,7 +7,7 @@ using TickerQ.Utilities.Models;
namespace Volo.Abp.BackgroundWorkers.TickerQ;
//TODO: Use lambda expression to improve performance.
public class TickerQPeriodicBackgroundWorkerInvoker
public class AbpTickerQPeriodicBackgroundWorkerInvoker
{
private readonly MethodInfo _doWorkAsyncMethod;
private readonly MethodInfo _doWorkMethod;
@ -15,7 +15,7 @@ public class TickerQPeriodicBackgroundWorkerInvoker
protected IBackgroundWorker Worker { get; }
protected IServiceProvider ServiceProvider { get; }
public TickerQPeriodicBackgroundWorkerInvoker(IBackgroundWorker worker, IServiceProvider serviceProvider)
public AbpTickerQPeriodicBackgroundWorkerInvoker(IBackgroundWorker worker, IServiceProvider serviceProvider)
{
_doWorkAsyncMethod = worker.GetType().GetMethod("DoWorkAsync", BindingFlags.Instance | BindingFlags.NonPublic)!;
_doWorkMethod = worker.GetType().GetMethod("DoWork", BindingFlags.Instance | BindingFlags.NonPublic)!;

15
modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.TickerQ/CleanupJobs.cs

@ -0,0 +1,15 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using TickerQ.Utilities.Models;
namespace Volo.Abp.BackgroundJobs.DemoApp.TickerQ;
public class CleanupJobs
{
public async Task CleanupLogsAsync(TickerFunctionContext<string> tickerContext, CancellationToken cancellationToken)
{
var logFileName = tickerContext.Request;
Console.WriteLine($"Cleaning up log file: {logFileName} at {DateTime.Now}");
}
}

56
modules/background-jobs/app/Volo.Abp.BackgroundJobs.DemoApp.TickerQ/DemoAppTickerQModule.cs

@ -1,10 +1,14 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using TickerQ.Dashboard.DependencyInjection;
using TickerQ.DependencyInjection;
using TickerQ.Utilities;
using TickerQ.Utilities.Enums;
using TickerQ.Utilities.Interfaces.Managers;
using TickerQ.Utilities.Models;
using TickerQ.Utilities.Models.Ticker;
using Volo.Abp.AspNetCore;
using Volo.Abp.Autofac;
@ -14,6 +18,7 @@ using Volo.Abp.BackgroundJobs.TickerQ;
using Volo.Abp.BackgroundWorkers;
using Volo.Abp.BackgroundWorkers.TickerQ;
using Volo.Abp.Modularity;
using Volo.Abp.TickerQ;
namespace Volo.Abp.BackgroundJobs.DemoApp.TickerQ;
@ -42,18 +47,43 @@ public class DemoAppTickerQModule : AbpModule
Configure<AbpBackgroundJobsTickerQOptions>(options =>
{
options.AddJobConfiguration<WriteToConsoleGreenJob>(new AbpBackgroundJobsTimeTickerConfiguration()
options.AddConfiguration<WriteToConsoleGreenJob>(new AbpBackgroundJobsTimeTickerConfiguration()
{
Retries = 3,
RetryIntervals = new[] {30, 60, 120}, // Retry after 30s, 60s, then 2min
RetryIntervals = new[] {30, 60, 120}, // Retry after 30s, 60s, then 2min,
Priority = TickerTaskPriority.High
});
options.AddJobConfiguration<WriteToConsoleYellowJob>(new AbpBackgroundJobsTimeTickerConfiguration()
options.AddConfiguration<WriteToConsoleYellowJob>(new AbpBackgroundJobsTimeTickerConfiguration()
{
Retries = 5,
RetryIntervals = new[] {30, 60, 120}, // Retry after 30s, 60s, then 2min
});
});
Configure<AbpBackgroundWorkersTickerQOptions>(options =>
{
options.AddConfiguration<MyBackgroundWorker>(new AbpBackgroundWorkersCronTickerConfiguration()
{
Retries = 3,
RetryIntervals = new[] {30, 60, 120}, // Retry after 30s, 60s, then 2min,
Priority = TickerTaskPriority.High
});
});
}
public override Task OnPreApplicationInitializationAsync(ApplicationInitializationContext context)
{
var abpTickerQFunctionProvider = context.ServiceProvider.GetRequiredService<AbpTickerQFunctionProvider>();
abpTickerQFunctionProvider.Functions.TryAdd(nameof(CleanupJobs), (string.Empty, TickerTaskPriority.Normal, new TickerFunctionDelegate(async (cancellationToken, serviceProvider, tickerFunctionContext) =>
{
var service = new CleanupJobs();
var request = await TickerRequestProvider.GetRequestAsync<string>(serviceProvider, tickerFunctionContext.Id, tickerFunctionContext.Type);
var genericContext = new TickerFunctionContext<string>(tickerFunctionContext, request);
await service.CleanupLogsAsync(genericContext, cancellationToken);
})));
abpTickerQFunctionProvider.RequestTypes.TryAdd(nameof(CleanupJobs), (typeof(string).FullName, typeof(string)));
return Task.CompletedTask;
}
public override async Task OnApplicationInitializationAsync(ApplicationInitializationContext context)
@ -64,6 +94,26 @@ public class DemoAppTickerQModule : AbpModule
var app = context.GetApplicationBuilder();
app.UseAbpTickerQ();
var timeTickerManager = context.ServiceProvider.GetRequiredService<ITimeTickerManager<TimeTicker>>();
await timeTickerManager.AddAsync(new TimeTicker
{
Function = nameof(CleanupJobs),
ExecutionTime = DateTime.UtcNow.AddSeconds(5),
Request = TickerHelper.CreateTickerRequest<string>("cleanup_example_file.txt"),
Retries = 3,
RetryIntervals = new[] { 30, 60, 120 }, // Retry after 30s, 60s, then 2min
});
var cronTickerManager = context.ServiceProvider.GetRequiredService<ICronTickerManager<CronTicker>>();
await cronTickerManager.AddAsync(new CronTicker
{
Function = nameof(CleanupJobs),
Expression = "* * * * *", // Every minute
Request = TickerHelper.CreateTickerRequest<string>("cleanup_example_file.txt"),
Retries = 2,
RetryIntervals = new[] { 60, 300 }
});
app.UseRouting();
app.UseEndpoints(endpoints =>
{

Loading…
Cancel
Save