This is a framework for wrapping Hangfire with an opinionated syntax for queueing jobs. It essentially draws inspiration from .NET MVC middleware configuration with the following goals.
- Encourage scalars when defining job options.
- Use "convention over configuration" when queueing jobs.
- Create abstractions to make testing easier.
A job should be defined in a single class which is instantiated by the global
IJobRunner. By convention you should create a job options class, the job
handler class and an helper extension on the job runner.
While this sample application doesn't feature validation on IJobOptions, it is
recommended. Validation should take place on the job runner when a job is
scheduled.
/**
* Options will be serialized when scheduling the job.
* They should be scalers or other values that serialize
* easily.
*/
public class LongRunningJobOptions : IJobOptions
{
public int TaskTime { get; set; } = 2;
}
/**
* The Job class will be instantiated by the Worker process
* and should have been configured with an IoC to simplify testing.
*/
public class LongRunningJob : IJob<LongRunningJobOptions>
{
public void Perform(LongRunningJobOptions options)
{
Console.WriteLine("LongRunningTask: Started");
var stopWatch = Stopwatch.StartNew();
Thread.Sleep(TimeSpan.FromSeconds(options.TaskTime));
Console.WriteLine($"LongRunningTask: Finished ({stopWatch.Elapsed})");
}
}
/**
* Adding a helper method on the +IJobRunner+ provides a
* cleaner API when testing and reading through application
* code.
*/
public static class LongRunningJobExtension
{
public static void QueueLongRunningJob(this IJobRunner jobRunner, Action<LongRunningJobOptions> configureJob)
{
jobRunner.Queue<LongRunningJob, LongRunningJobOptions>(configureJob);
}
}
/**
* With the options class and helper method defined we
* can queue a job with a simple api.
*/
public void Main(IJobRunner jobRunner)
{
jobRunner.QueueLongRunningJob(options => { options.TaskTime = 10; });
}$ git clone https://github.com/BaylorRae/hangfire-framework-sample.git
$ cd hangfire-framework-sample
# build the frontend and worker projects
$ docker-compose build
# start everything as a daemon
$ docker-compose up -d
# follow the logs for frontend and worker1
$ docker-compose logs -f frontend worker1This project is designed to keep all 3rd party dependencies in the top most
layers (e.g. frontend, worker and common). This is accomplished by
wrapping all third party apis with internal interfaces in our core project.
