- Implement background jobs through interfaces
- Centralized host to manage and run jobs, keeping memory and thread usage low.
- Dependency Injection support
- Read and update job schedules at runtime through
IConfiguration
orIOptionsMonitor
- Monitoring jobs using logs and metrics, both compatible with OpenTelemetry
- Cron expressions using
ICronJob
- Recurringly at a set interval using
IRecurringJob
- Recurringly at a set interval after an initial delay using
IRecurringJobWithInitialDelay
- Once at an absolute time using
IOneTimeJob
- Sending emails
- Processing data
- Enforcing data retention
Make BackgroundJobs by implementing one of these interfaces:
public class CronJob : ICronJob
{
public Task RunJobAsync(CancellationToken cancellationToken = default)
{
Console.WriteLine("Time to backup your databases!");
return Task.CompletedTask;
}
public CronExpression CronExpression => CronExpression.Parse("0 3 * * *");
}
public class RecurringJob : IRecurringJob
{
public Task RunJobAsync(CancellationToken cancellationToken = default)
{
Console.WriteLine("This is your hourly reminder to stay hydrated.");
return Task.CompletedTask;
}
public TimeSpan Interval => TimeSpan.FromHours(1);
}
public class RecurringJobWithInitialDelay : IRecurringJobWithInitialDelay
{
public Task RunJobAsync(CancellationToken cancellationToken = default)
{
Console.WriteLine("This is your hourly reminder to stay hydrated.");
return Task.CompletedTask;
}
public TimeSpan Interval => TimeSpan.FromHours(1);
public TimeSpan InitialDelay => TimeSpan.Zero;
}
public class OneTimeJob : IOneTimeJob
{
public Task RunJobAsync(CancellationToken cancellationToken = default)
{
Console.WriteLine("Happy New Year!");
return Task.CompletedTask;
}
public DateTime ScheduledTimeUtc => new(year: 2023, month: 12, day: 31, hour: 23, minute: 59, second: 59);
}
Call AddBackgroundJobs()
on an IServiceCollection
, and then add jobs:
builder.Services.AddBackgroundJobs()
.AddJob<CronJob>()
.AddJob<RecurringJob>()
.AddJob<RecurringJobWithInitialDelay>()
.AddJob<OneTimeJob>();
You can also register jobs in-line for simple use cases:
builder.Services.AddBackgroundJobs()
.AddJob(
name: "basic-cronjob",
job: () => {},
cronExpression: CronExpression.Parse("* * * * *"))
.AddJob(
name: "basic-recurringjob",
job: () => {},
interval: TimeSpan.FromSeconds(3))
.AddJob(
name: "basic-recurringjob-withinitialdelay",
job: () => {},
interval: TimeSpan.FromSeconds(3),
initialDelay: TimeSpan.Zero)
.AddJob(
name: "basic-onetimejob",
job: () => {},
scheduledTimeUtc: DateTime.UtcNow.AddHours(1))
.AddAsyncJob(
name: "async-cronjob",
job: cancellationToken => Task.CompletedTask,
cronExpression: CronExpression.Parse("* * * * *"))
.AddAsyncJob(
name: "async-recurringjob",
job: cancellationToken => Task.CompletedTask,
interval: TimeSpan.FromSeconds(3))
.AddAsyncJob(
name: "async-recurringjob-withinitialdelay",
job: cancellationToken => Task.CompletedTask,
interval: TimeSpan.FromSeconds(3),
initialDelay: TimeSpan.Zero)
.AddAsyncJob(
name: "async-onetimejob",
job: cancellationToken => Task.CompletedTask,
scheduledTimeUtc: DateTime.UtcNow.AddHours(1));
Sample 🔗 | Tags |
---|---|
BackgroundJobs.Configuration | ASP.NET, Reloading, Configuration |
BackgroundJobs.MinimalAPI | ASP.NET, MinimalAPI |
BackgroundJobs.OpenTelemetry | ASP.NET, Open Telemetry, Metrics, Logs |
BackgroundJobs.WorkerService | Console, Worker Service |
Each project exposes histogram metrics, which allow monitoring the duration and count of jobs.
The meter names match the project names.
The Open Telemetry Sample shows how to collect CronJob metrics using the Prometheus Open Telemetry exporter.
Replace Assembly Scanning with registration similar to that of HealthChecks- A separate UI project to help visualize when jobs trigger
- Utilize dotnet 8's new TimeProvider instead of
DateTime.UtcNow
- More samples
- Using Blazor Server
Using a Worker Service- Using IConfiguration to reload job schedule
- Using OneTimeJobs to control feature flags
- Using RecurringJobs to manage data retention
- The developers of Cronos for their excellent Cron expression library.
- JetBrains for providing me with a free license to their products, through their Open Source Support program.