Skip to content

Commit 98ff26d

Browse files
authored
Merge pull request #23802 from abpframework/copilot/fix-d5496b38-0efc-4016-8ab2-970b67675314
Add TickerQ Background Worker Integration
2 parents 4918b63 + e8359d1 commit 98ff26d

File tree

41 files changed

+1206
-8
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1206
-8
lines changed

.github/workflows/build-and-test.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ jobs:
5959
- uses: actions/setup-dotnet@master
6060
with:
6161
dotnet-version: 10.0.x
62-
6362
- name: Build All
6463
run: ./build-all.ps1
6564
working-directory: ./build

Directory.Packages.props

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,10 @@
182182
<PackageVersion Include="System.Threading.Tasks.Extensions" Version="4.6.3" />
183183
<PackageVersion Include="TencentCloudSDK.Sms" Version="3.0.1273" />
184184
<PackageVersion Include="TimeZoneConverter" Version="7.0.0" />
185+
<PackageVersion Include="TickerQ" Version="2.5.3" />
186+
<PackageVersion Include="TickerQ.Dashboard" Version="2.5.3" />
187+
<PackageVersion Include="TickerQ.Utilities" Version="2.5.3" />
188+
<PackageVersion Include="TickerQ.EntityFrameworkCore" Version="2.5.3" />
185189
<PackageVersion Include="Unidecode.NET" Version="2.1.0" />
186190
<PackageVersion Include="xunit" Version="2.9.3" />
187191
<PackageVersion Include="xunit.extensibility.execution" Version="2.9.3" />

docs/en/docs-nav.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,10 @@
571571
{
572572
"text": "Quartz Integration",
573573
"path": "framework/infrastructure/background-jobs/quartz.md"
574+
},
575+
{
576+
"text": "TickerQ Integration",
577+
"path": "framework/infrastructure/background-jobs/tickerq.md"
574578
}
575579
]
576580
},
@@ -589,6 +593,10 @@
589593
{
590594
"text": "Hangfire Integration",
591595
"path": "framework/infrastructure/background-workers/hangfire.md"
596+
},
597+
{
598+
"text": "TickerQ Integration",
599+
"path": "framework/infrastructure/background-workers/tickerq.md"
592600
}
593601
]
594602
},

docs/en/framework/infrastructure/background-jobs/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,7 @@ See pre-built job manager alternatives:
348348
* [Hangfire Background Job Manager](./hangfire.md)
349349
* [RabbitMQ Background Job Manager](./rabbitmq.md)
350350
* [Quartz Background Job Manager](./quartz.md)
351+
* [TickerQ Background Job Manager](./tickerq.md)
351352

352353
## See Also
353354
* [Background Workers](../background-workers)
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
# TickerQ Background Job Manager
2+
3+
[TickerQ](https://tickerq.net/) is a fast, reflection-free background task scheduler for .NET — built with source generators, EF Core integration, cron + time-based execution, and a real-time dashboard. You can integrate TickerQ with the ABP to use it instead of the [default background job manager](../background-jobs). In this way, you can use the same background job API for TickerQ and your code will be independent of TickerQ. If you like, you can directly use TickerQ's API, too.
4+
5+
> See the [background jobs document](../background-jobs) to learn how to use the background job system. This document only shows how to install and configure the TickerQ integration.
6+
7+
## Installation
8+
9+
It is suggested to use the [ABP CLI](../../../cli) to install this package.
10+
11+
### Using the ABP CLI
12+
13+
Open a command line window in the folder of the project (.csproj file) and type the following command:
14+
15+
````bash
16+
abp add-package Volo.Abp.BackgroundJobs.TickerQ
17+
````
18+
19+
> If you haven't done it yet, you first need to install the [ABP CLI](../../../cli). For other installation options, see [the package description page](https://abp.io/package-detail/Volo.Abp.BackgroundJobs.TickerQ).
20+
21+
## Configuration
22+
23+
### AddTickerQ
24+
25+
You can call the `AddTickerQ` extension method in the `ConfigureServices` method of your module to configure TickerQ services:
26+
27+
> This is optional. ABP will automatically register TickerQ services.
28+
29+
```csharp
30+
public override void ConfigureServices(ServiceConfigurationContext context)
31+
{
32+
context.Services.AddTickerQ(x =>
33+
{
34+
// Configure TickerQ options here
35+
});
36+
}
37+
```
38+
39+
### UseAbpTickerQ
40+
41+
You need to call the `UseAbpTickerQ` extension method instead of `AddTickerQ` in the `OnApplicationInitialization` method of your module:
42+
43+
```csharp
44+
// (default: TickerQStartMode.Immediate)
45+
app.UseAbpTickerQ(startMode: ...);
46+
```
47+
48+
### AbpBackgroundJobsTickerQOptions
49+
50+
You can configure the `TimeTicker` properties for specific jobs. For example, you can change `Priority`, `Retries` and `RetryIntervals` properties as shown below:
51+
52+
```csharp
53+
Configure<AbpBackgroundJobsTickerQOptions>(options =>
54+
{
55+
options.AddJobConfiguration<MyBackgroundJob>(new AbpBackgroundJobsTimeTickerConfiguration()
56+
{
57+
Retries = 3,
58+
RetryIntervals = new[] {30, 60, 120}, // Retry after 30s, 60s, then 2min
59+
Priority = TickerTaskPriority.High
60+
61+
// Optional batching
62+
//BatchParent = Guid.Parse("...."),
63+
//BatchRunCondition = BatchRunCondition.OnSuccess
64+
});
65+
66+
options.AddJobConfiguration<MyBackgroundJob2>(new AbpBackgroundJobsTimeTickerConfiguration()
67+
{
68+
Retries = 5,
69+
RetryIntervals = new[] {30, 60, 120}, // Retry after 30s, 60s, then 2min
70+
Priority = TickerTaskPriority.Normal
71+
});
72+
});
73+
```
74+
75+
### Add your own TickerQ Background Jobs Definitions
76+
77+
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.
78+
79+
For example, you can add a `CleanupJobs` job definition in the `OnPreApplicationInitializationAsync` method of your module:
80+
81+
```csharp
82+
public class CleanupJobs
83+
{
84+
public async Task CleanupLogsAsync(TickerFunctionContext<string> tickerContext, CancellationToken cancellationToken)
85+
{
86+
var logFileName = tickerContext.Request;
87+
Console.WriteLine($"Cleaning up log file: {logFileName} at {DateTime.Now}");
88+
}
89+
}
90+
```
91+
92+
```csharp
93+
public override Task OnPreApplicationInitializationAsync(ApplicationInitializationContext context)
94+
{
95+
var abpTickerQFunctionProvider = context.ServiceProvider.GetRequiredService<AbpTickerQFunctionProvider>();
96+
abpTickerQFunctionProvider.Functions.TryAdd(nameof(CleanupJobs), (string.Empty, TickerTaskPriority.Normal, new TickerFunctionDelegate(async (cancellationToken, serviceProvider, tickerFunctionContext) =>
97+
{
98+
var service = new CleanupJobs(); // Or get it from the serviceProvider
99+
var request = await TickerRequestProvider.GetRequestAsync<string>(serviceProvider, tickerFunctionContext.Id, tickerFunctionContext.Type);
100+
var genericContext = new TickerFunctionContext<string>(tickerFunctionContext, request);
101+
await service.CleanupLogsAsync(genericContext, cancellationToken);
102+
})));
103+
abpTickerQFunctionProvider.RequestTypes.TryAdd(nameof(CleanupJobs), (typeof(string).FullName, typeof(string)));
104+
return Task.CompletedTask;
105+
}
106+
```
107+
108+
And then you can add a job by using the `ITimeTickerManager<TimeTicker>`:
109+
110+
```csharp
111+
var timeTickerManager = context.ServiceProvider.GetRequiredService<ITimeTickerManager<TimeTicker>>();
112+
await timeTickerManager.AddAsync(new TimeTicker
113+
{
114+
Function = nameof(CleanupJobs),
115+
ExecutionTime = DateTime.UtcNow.AddSeconds(5),
116+
Request = TickerHelper.CreateTickerRequest<string>("cleanup_example_file.txt"),
117+
Retries = 3,
118+
RetryIntervals = new[] { 30, 60, 120 }, // Retry after 30s, 60s, then 2min
119+
});
120+
```
121+
122+
### TickerQ Dashboard and EF Core Integration
123+
124+
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.
125+

docs/en/framework/infrastructure/background-workers/index.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ Start your worker in the `StartAsync` (which is called when the application begi
4141

4242
Assume that we want to make a user passive, if the user has not logged in to the application in last 30 days. `AsyncPeriodicBackgroundWorkerBase` class simplifies to create periodic workers, so we will use it for the example below:
4343

44-
> You can use `CronExpression` property to set the cron expression for the background worker if you will use the [Hangfire Background Worker Manager](./hangfire.md) or [Quartz Background Worker Manager](./quartz.md).
44+
> You can use `CronExpression` property to set the cron expression for the background worker if you will use the [Hangfire Background Worker Manager](./hangfire.md), [Quartz Background Worker Manager](./quartz.md), or [TickerQ Background Worker Manager](./tickerq.md).
4545
4646
````csharp
4747
public class PassiveUserCheckerWorker : AsyncPeriodicBackgroundWorkerBase
@@ -216,7 +216,8 @@ Background worker system is extensible and you can change the default background
216216
See pre-built worker manager alternatives:
217217

218218
* [Quartz Background Worker Manager](./quartz.md)
219-
* [Hangfire Background Worker Manager](./hangfire.md)
219+
* [Hangfire Background Worker Manager](./hangfire.md)
220+
* [TickerQ Background Worker Manager](./tickerq.md)
220221

221222
## See Also
222223

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
# TickerQ Background Worker Manager
2+
3+
[TickerQ](https://tickerq.net/) is a fast, reflection-free background task scheduler for .NET — built with source generators, EF Core integration, cron + time-based execution, and a real-time dashboard. You can integrate TickerQ with the ABP to use it instead of the [default background worker manager](../background-workers).
4+
5+
## Installation
6+
7+
It is suggested to use the [ABP CLI](../../../cli) to install this package.
8+
9+
### Using the ABP CLI
10+
11+
Open a command line window in the folder of the project (.csproj file) and type the following command:
12+
13+
````bash
14+
abp add-package Volo.Abp.BackgroundWorkers.TickerQ
15+
````
16+
17+
> If you haven't done it yet, you first need to install the [ABP CLI](../../../cli). For other installation options, see [the package description page](https://abp.io/package-detail/Volo.Abp.BackgroundWorkers.TickerQ).
18+
19+
## Configuration
20+
21+
### AddTickerQ
22+
23+
You can call the `AddTickerQ` extension method in the `ConfigureServices` method of your module to configure TickerQ services:
24+
25+
> This is optional. ABP will automatically register TickerQ services.
26+
27+
```csharp
28+
public override void ConfigureServices(ServiceConfigurationContext context)
29+
{
30+
context.Services.AddTickerQ(x =>
31+
{
32+
// Configure TickerQ options here
33+
});
34+
}
35+
```
36+
37+
### UseAbpTickerQ
38+
39+
You need to call the `UseAbpTickerQ` extension method instead of `AddTickerQ` in the `OnApplicationInitialization` method of your module:
40+
41+
```csharp
42+
// (default: TickerQStartMode.Immediate)
43+
app.UseAbpTickerQ(startMode: ...);
44+
```
45+
46+
### AbpBackgroundWorkersTickerQOptions
47+
48+
You can configure the `CronTicker` properties for specific jobs. For example, Change `Priority`, `Retries` and `RetryIntervals` properties:
49+
50+
```csharp
51+
Configure<AbpBackgroundWorkersTickerQOptions>(options =>
52+
{
53+
options.AddConfiguration<MyBackgroundWorker>(new AbpBackgroundWorkersCronTickerConfiguration()
54+
{
55+
Retries = 3,
56+
RetryIntervals = new[] {30, 60, 120}, // Retry after 30s, 60s, then 2min,
57+
Priority = TickerTaskPriority.High
58+
});
59+
});
60+
```
61+
62+
### Add your own TickerQ Background Worker Definitions
63+
64+
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.
65+
66+
For example, you can add a `CleanupJobs` job definition in the `OnPreApplicationInitializationAsync` method of your module:
67+
68+
```csharp
69+
public class CleanupJobs
70+
{
71+
public async Task CleanupLogsAsync(TickerFunctionContext<string> tickerContext, CancellationToken cancellationToken)
72+
{
73+
var logFileName = tickerContext.Request;
74+
Console.WriteLine($"Cleaning up log file: {logFileName} at {DateTime.Now}");
75+
}
76+
}
77+
```
78+
79+
```csharp
80+
public override Task OnPreApplicationInitializationAsync(ApplicationInitializationContext context)
81+
{
82+
var abpTickerQFunctionProvider = context.ServiceProvider.GetRequiredService<AbpTickerQFunctionProvider>();
83+
abpTickerQFunctionProvider.Functions.TryAdd(nameof(CleanupJobs), (string.Empty, TickerTaskPriority.Normal, new TickerFunctionDelegate(async (cancellationToken, serviceProvider, tickerFunctionContext) =>
84+
{
85+
var service = new CleanupJobs(); // Or get it from the serviceProvider
86+
var request = await TickerRequestProvider.GetRequestAsync<string>(serviceProvider, tickerFunctionContext.Id, tickerFunctionContext.Type);
87+
var genericContext = new TickerFunctionContext<string>(tickerFunctionContext, request);
88+
await service.CleanupLogsAsync(genericContext, cancellationToken);
89+
})));
90+
abpTickerQFunctionProvider.RequestTypes.TryAdd(nameof(CleanupJobs), (typeof(string).FullName, typeof(string)));
91+
return Task.CompletedTask;
92+
}
93+
```
94+
95+
And then you can add a job by using the `ICronTickerManager<CronTicker>`:
96+
97+
```csharp
98+
var cronTickerManager = context.ServiceProvider.GetRequiredService<ICronTickerManager<CronTicker>>();
99+
await cronTickerManager.AddAsync(new CronTicker
100+
{
101+
Function = nameof(CleanupJobs),
102+
Expression = "0 */6 * * *", // Every 6 hours
103+
Request = TickerHelper.CreateTickerRequest<string>("cleanup_example_file.txt"),
104+
Retries = 2,
105+
RetryIntervals = new[] { 60, 300 }
106+
});
107+
```
108+
109+
You can specify a cron expression instead of use `ICronTickerManager<CronTicker>` to add a worker:
110+
111+
```csharp
112+
abpTickerQFunctionProvider.Functions.TryAdd(nameof(CleanupJobs), (string.Empty, TickerTaskPriority.Normal, new TickerFunctionDelegate(async (cancellationToken, serviceProvider, tickerFunctionContext) =>
113+
{
114+
var service = new CleanupJobs();
115+
var request = await TickerRequestProvider.GetRequestAsync<string>(serviceProvider, tickerFunctionContext.Id, tickerFunctionContext.Type);
116+
var genericContext = new TickerFunctionContext<string>(tickerFunctionContext, request);
117+
await service.CleanupLogsAsync(genericContext, cancellationToken);
118+
})));
119+
```

framework/Volo.Abp.slnx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,9 @@
166166
<Project Path="src/Volo.Abp/Volo.Abp.csproj" />
167167
<Project Path="src/Volo.Abp.AI.Abstractions/Volo.Abp.AI.Abstractions.csproj" />
168168
<Project Path="src/Volo.Abp.AI/Volo.Abp.AI.csproj" />
169+
<Project Path="src/Volo.Abp.TickerQ/Volo.Abp.TickerQ.csproj" />
170+
<Project Path="src/Volo.Abp.BackgroundJobs.TickerQ/Volo.Abp.BackgroundJobs.TickerQ.csproj" />
171+
<Project Path="src/Volo.Abp.BackgroundWorkers.TickerQ/Volo.Abp.BackgroundWorkers.TickerQ.csproj" />
169172
</Folder>
170173
<Folder Name="/test/">
171174
<Project Path="test/AbpTestBase/AbpTestBase.csproj" />
@@ -252,4 +255,4 @@
252255
<Project Path="test/Volo.Abp.Validation.Tests/Volo.Abp.Validation.Tests.csproj" />
253256
<Project Path="test/Volo.Abp.VirtualFileSystem.Tests/Volo.Abp.VirtualFileSystem.Tests.csproj" />
254257
</Folder>
255-
</Solution>
258+
</Solution>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
2+
<ConfigureAwait ContinueOnCapturedContext="false" />
3+
</Weavers>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
3+
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
4+
<xs:element name="Weavers">
5+
<xs:complexType>
6+
<xs:all>
7+
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
8+
<xs:complexType>
9+
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
10+
</xs:complexType>
11+
</xs:element>
12+
</xs:all>
13+
<xs:attribute name="VerifyAssembly" type="xs:boolean">
14+
<xs:annotation>
15+
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
16+
</xs:annotation>
17+
</xs:attribute>
18+
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
19+
<xs:annotation>
20+
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
21+
</xs:annotation>
22+
</xs:attribute>
23+
<xs:attribute name="GenerateXsd" type="xs:boolean">
24+
<xs:annotation>
25+
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
26+
</xs:annotation>
27+
</xs:attribute>
28+
</xs:complexType>
29+
</xs:element>
30+
</xs:schema>

0 commit comments

Comments
 (0)