AppVeyor | Travis |
---|---|
A background processing library for Asp.Net Core.
Note that this is in development so incompatible changes can happen between minor versions. (Starting from 0.7.0
, the api is stabalizing and there'll probably be no breaking changes in the database schema)
This was inspired by Hangfire but this is a complete (and a more lightweight) rewrite. I'll refer to this library as "Jobs".
Jobs integrates well with Asp.Net Core and its dependency injection system with the following features:
- Provides a way to schedule 3 types of background jobs:
- Fire and forget: These are jobs that need to be executed in the background some time later (preferably very soon).
- Delayed: These are jobs that need to be executed after a certain delay (minimally).
- Cron: These are cron jobs that execute regularly at certain points in time (for example daily or monthly).
- Jobs are persisted so that whenever you schedule a job it's guaranteed to be executed at some point in the future even if the application restarts and stays offline for days.
- Asynchronous processing pipeline: all jobs can be asynchronous.
MR.AspNetCore.Jobs.SqlServer
: Microsoft's Sql ServerMR.AspNetCore.Jobs.InMemory
: InMemory [Coming Soon]MR.AspNetCore.Jobs.PostgreSQL
: PostgreSQL [Coming Soon, maybe]MR.AspNetCore.Jobs.MySql
: MySql [Coming Soon, maybe]MR.AspNetCore.Jobs.Sqlite
: Sqlite [Coming Soon, maybe]MR.AspNetCore.Jobs.Redis
: Redis [Coming Soon, maybe]
public void ConfigureServices(IServiceCollection services)
{
...
// Registers Jobs with an sql server adapter
services.AddJobs(options => options.UseSqlServer("[my connection string]"));
}
public static async Task Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
await host.StartJobsAsync();
using (var scope = host.Services.CreateScope())
{
var context = scope.ServiceProvider.GetService<AppDbContext>();
await context.Database.MigrateAsync();
}
host.Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
If you're not using latest C# version and therefore can't use async Main
, you can simply do:
host.StartJobsAsync().GetAwaiter().GetResult();
Anywhere you want to enqueue a background job you use IJobsManager
, use DI to get it injected:
public class HomeController : Controller
{
private IJobsManager _jobsManager;
public HomeController(IJobsManager jobsManager)
{
_jobsManager = jobsManager;
}
public async Task<IActionResult> Home()
{
await _jobsManager.EnqueueAsync(...);
return View();
}
}
// Execute a static method.
await _jobsManager.EnqueueAsync(() => SomeStaticClass.SomeStaticMethod("foo"));
// Execute an instance method. FooService will be created using DI so it is injectable.
await _jobsManager.EnqueueAsync<FooService>(service => service.SomeMethod("foo"));
// Execute after 1 minute.
await _jobsManager.EnqueueAsync(() => ..., TimeSpan.FromMinutes(1));
All methods (fire and forget + delayed) can be async (return Task) and they'll be correctly awaited.
First, we'll have to create a registry that describes all the cron jobs we want to run:
public class FooJob : IJob
{
ILogger<FooJob> _logger;
// This is injectable so make sure you add FooJob to DI.
public FooJob(ILogger<FooJob> logger)
{
_logger = logger;
}
public Task ExecuteAsync()
{
// Do stuff
_logger.LogInformation("FooJob is executing!");
return Task.FromResult(0);
}
}
public class SomeCronJobRegistry : CronJobRegistry
{
public SomeCronJobRegistry()
{
// Use RegisterJob to register cron jobs:
// - FooJob should be added to DI because it will be injected when executing the job.
// - Give the job a unique name.
// - Use the Cron class to create various kinds of cron expressions.
RegisterJob<FooJob>(nameof(FooJob), Cron.Minutely());
}
}
You can extend
JobSync
if your job is inherently synchronous.
Then, we tell Jobs to use this registry:
services.AddJobs(options =>
{
options.UseSqlServer("[my connection string]");
// Use the SomeCronJobRegistry.
options.UseCronJobRegistry<SomeCronJobRegistry>();
});
After the processing server starts it will know when to execute cron jobs whenever needed without your intervention.
All kinds of jobs can be given different retrying behaviors. For delayed jobs, you are required to implement your job inside a class that implements IRetryable
, else the default behavior will be used. IRetryable
has one property called RetryBehavior
that returns an instance of RetryBehavior
which will be used to determine whether and when to retry a failed job before marking it as failed. You can use RetryBehavior.DefaultRetry
, RetryBehavior.NoRetry
, or your own subclass that overrides this behavior.
Basic
: implements Jobs in an Asp.Net Core app.