|
| 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 | + |
0 commit comments