Skip to content

Commit c7d2bb4

Browse files
committed
updates
1 parent f2da150 commit c7d2bb4

File tree

4 files changed

+159
-48
lines changed

4 files changed

+159
-48
lines changed

MyApp/_pages/background-jobs.md

Lines changed: 7 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -180,52 +180,6 @@ the following options:
180180
- `ReplyTo` - Optional field for capturing where to send notification for completion of a Job
181181
- `Args` - Optional String Dictionary of Arguments that can be attached to a Job
182182

183-
### Schedule Recurring Tasks
184-
185-
In addition to queueing jobs to run in the background, it also supports scheduling recurring tasks
186-
to execute APIs or Commands at fixed intervals.
187-
188-
:::youtube DtB8KaXXMCM
189-
Schedule your Reoccurring Tasks with Background Jobs!
190-
:::
191-
192-
APIs and Commands can be scheduled to run at either a `TimeSpan` or
193-
[CRON Expression](https://github.com/HangfireIO/Cronos?tab=readme-ov-file#cron-format) interval, e.g:
194-
195-
```csharp
196-
jobs.RecurringCommand<CheckUrlsCommand>(Schedule.Cron("* * * * *"));
197-
jobs.RecurringCommand<CheckUrlsCommand>(
198-
Schedule.Interval(TimeSpan.FromMinutes(1)));
199-
200-
jobs.RecurringCommand<CheckUrlsCommand>(Schedule.EveryMinute, new CheckUrls {
201-
Urls = urls
202-
});
203-
204-
jobs.RecurringApi(Schedule.Interval(TimeSpan.FromMinutes(1)), new CheckUrls {
205-
Urls = urls
206-
});
207-
```
208-
209-
That can be registered with an optional **Task Name** and **Background Options**, e.g:
210-
211-
```csharp
212-
jobs.RecurringCommand<CheckUrlsCommand>("Check URLs", Schedule.EveryMinute,
213-
new() {
214-
RunCommand = true // don't persist job
215-
});
216-
```
217-
218-
:::info
219-
If no name is provided, the Command's Name or APIs Request DTO will be used
220-
:::
221-
222-
Scheduled Tasks are idempotent where the same registration with the same name will
223-
either create or update the scheduled task registration without losing track of the
224-
last time the Recurring Task was run which is also viewable in the Jobs Admin UI:
225-
226-
![](/img/pages/jobs/jobs-scheduled-tasks-last-job.webp)
227-
228-
As such it's recommended to always define your App's Scheduled Tasks on Startup:
229183

230184
### Executing non-durable jobs
231185

@@ -371,9 +325,9 @@ Where any dependent jobs are only executed if the job was successfully completed
371325
If instead an exception was thrown during execution, the job will be failed and
372326
all its dependent jobs cancelled and removed from the queue.
373327

374-
### Executing jobs with an Authenticated User Context
328+
### Executing jobs with an Authorized User Context
375329

376-
If you have existing logic dependent on a Authenticated `ClaimsPrincipal` or ServiceStack
330+
If you have logic dependent on an Authenticated `ClaimsPrincipal` or ServiceStack
377331
`IAuthSession` you can have your APIs and Commands also be executed with that user context
378332
by specifying the `UserId` the job should be executed as:
379333

@@ -449,14 +403,19 @@ var jobRef = jobs.EnqueueCommand<CreateOpenAiChatCommand>(openAiRequest,
449403
new() {
450404
// Group related jobs under a common tag
451405
Tag = "ai",
406+
452407
// A User-specified or system generated unique Id to track the job
453408
RefId = request.RefId,
409+
454410
// Capture who created the job
455411
CreatedBy = Request.GetClaimsPrincipal().GetUserName(),
412+
456413
// Link jobs together that are sent together in a batch
457414
BatchId = batchId,
415+
458416
// Capture where to notify the completion of the job to
459417
ReplyTo = "https:example.org/callback",
418+
460419
// Additional properties about the job that aren't in the Request
461420
Args = new() {
462421
["Additional"] = "Metadata"

MyApp/_pages/recurring-tasks.md

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
---
2+
title: Schedule Recurring Tasks
3+
---
4+
5+
In addition to queueing jobs to run in the background, it also supports scheduling recurring tasks
6+
to execute APIs or Commands at fixed intervals.
7+
8+
:::youtube DtB8KaXXMCM
9+
Schedule your Reoccurring Tasks with Background Jobs!
10+
:::
11+
12+
APIs and Commands can be scheduled to run at either a `TimeSpan` or
13+
[CRON Expression](https://github.com/HangfireIO/Cronos?tab=readme-ov-file#cron-format) interval, e.g:
14+
15+
16+
## CRON Expression Examples
17+
18+
```csharp
19+
// Every Minute Expression
20+
jobs.RecurringCommand<CheckUrlsCommand>(Schedule.Cron("* * * * *"));
21+
22+
// Every Minute Constant
23+
jobs.RecurringCommand<CheckUrlsCommand>(Schedule.EveryMinute, new CheckUrls {
24+
Urls = urls
25+
});
26+
```
27+
28+
### CRON Format
29+
30+
You can use any **unix-cron format** expression supported by the [HangfireIO/Cronos](https://github.com/HangfireIO/Cronos) library:
31+
32+
```txt
33+
|------------------------------- Minute (0-59)
34+
| |------------------------- Hour (0-23)
35+
| | |------------------- Day of the month (1-31)
36+
| | | |------------- Month (1-12; or JAN to DEC)
37+
| | | | |------- Day of the week (0-6; or SUN to SAT; or 7 for Sunday)
38+
| | | | |
39+
| | | | |
40+
* * * * *
41+
```
42+
43+
The allowed formats for each field include:
44+
45+
| Field | Format of valid values |
46+
|------------------|--------------------------------------------|
47+
| Minute | 0-59 |
48+
| Hour | 0-23 |
49+
| Day of the month | 1-31 |
50+
| Month | 1-12 (or JAN to DEC) |
51+
| Day of the week | 0-6 (or SUN to SAT; or 7 for Sunday) |
52+
53+
### Matching all values
54+
55+
To match all values for a field, use the asterisk: `*`, e.g here are two examples in which the minute field is left unrestricted:
56+
57+
- `* 0 1 1 1` - the job runs every minute of the midnight hour on January 1st and Mondays.
58+
- `* * * * *` - the job runs every minute (of every hour, of every day of the month, of every month, every day of the week, because each of these fields is unrestricted too).
59+
60+
### Matching a range
61+
62+
To match a range of values, specify your start and stop values, separated by a hyphen (-). Do not include spaces in the range. Ranges are inclusive. The first value must be less than the second.
63+
64+
The following equivalent examples run at midnight on Mondays, Tuesdays, Wednesdays, Thursdays, and Fridays (for all months):
65+
66+
- `0 0 * * 1-5`
67+
- `0 0 * * MON-FRI`
68+
69+
### Matching a list
70+
71+
Lists can contain any valid value for the field, including ranges. Specify your values, separated by a comma (,). Do not include spaces in the list, e.g:
72+
73+
- `0 0,12 * * *` - the job runs at midnight and noon.
74+
- `0-5,30-35 * * * *` - the job runs in each of the first five minutes of every half hour (at the top of the hour and at half past the hour).
75+
76+
## TimeSpan Interval Examples
77+
78+
```csharp
79+
jobs.RecurringCommand<CheckUrlsCommand>(Schedule.Interval(TimeSpan.FromMinutes(1)));
80+
81+
// With Example
82+
jobs.RecurringApi(Schedule.Interval(TimeSpan.FromMinutes(1)), new CheckUrls {
83+
Urls = urls
84+
});
85+
```
86+
87+
That can be registered with an optional **Task Name** and **Background Options**, e.g:
88+
89+
```csharp
90+
jobs.RecurringCommand<CheckUrlsCommand>("Check URLs", Schedule.EveryMinute,
91+
new() {
92+
RunCommand = true // don't persist job
93+
});
94+
```
95+
96+
:::info
97+
If no name is provided, the Command's Name or APIs Request DTO will be used
98+
:::
99+
100+
## Idempotent Registration
101+
102+
Scheduled Tasks are idempotent where the same registration with the same name will
103+
either create or update the scheduled task registration without losing track of the
104+
last time the Recurring Task, as such it's recommended to always define your App's
105+
Scheduled Tasks on Startup:
106+
107+
```csharp
108+
public class ConfigureBackgroundJobs : IHostingStartup
109+
{
110+
public void Configure(IWebHostBuilder builder) => builder
111+
.ConfigureServices((context,services) => {
112+
services.AddPlugin(new CommandsFeature());
113+
services.AddPlugin(new BackgroundsJobFeature());
114+
services.AddHostedService<JobsHostedService>();
115+
}).ConfigureAppHost(afterAppHostInit: appHost => {
116+
var services = appHost.GetApplicationServices();
117+
118+
var jobs = services.GetRequiredService<IBackgroundJobs>();
119+
120+
// App's Scheduled Tasks Registrations:
121+
jobs.RecurringCommand<MyCommand>(Schedule.Hourly);
122+
});
123+
}
124+
```
125+
126+
## Background Jobs Admin UI
127+
128+
The last job the Recurring Task ran is also viewable in the Jobs Admin UI:
129+
130+
![](/img/pages/jobs/jobs-scheduled-tasks-last-job.webp)

MyApp/_pages/releases/v8_04.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,24 @@ last time the Recurring Task was run which is also viewable in the Jobs Admin UI
243243

244244
As such it's recommended to always define your App's Scheduled Tasks on Startup:
245245

246+
```csharp
247+
public class ConfigureBackgroundJobs : IHostingStartup
248+
{
249+
public void Configure(IWebHostBuilder builder) => builder
250+
.ConfigureServices((context,services) => {
251+
services.AddPlugin(new CommandsFeature());
252+
services.AddPlugin(new BackgroundsJobFeature());
253+
services.AddHostedService<JobsHostedService>();
254+
}).ConfigureAppHost(afterAppHostInit: appHost => {
255+
var services = appHost.GetApplicationServices();
256+
257+
var jobs = services.GetRequiredService<IBackgroundJobs>();
258+
// Register Scheduled Tasks
259+
jobs.RecurringCommand<MyCommand>(Schedule.Hourly);
260+
});
261+
}
262+
```
263+
246264
### Executing non-durable jobs
247265

248266
`IBackgroundJobs` also supports `RunCommand` methods to be able to execute jobs transiently

MyApp/_pages/sidebar.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,10 @@
392392
"text": "Overview",
393393
"link": "/background-jobs"
394394
},
395+
{
396+
"text": "Schedule Recurring Tasks",
397+
"link": "/recurring-tasks"
398+
},
395399
{
396400
"text": "Commands",
397401
"link": "/commands"

0 commit comments

Comments
 (0)