This is the second part of a series discussing job scheduling and Hangfire details:
- part 1 - Why schedule and procrastinate jobs?
- part 2 - Overview of Hangfie
- part 3 - Scheduling and Queuing jobs in Hangfire
- part 4 - Dashboard, retries and job cancellation
- part 5 - Job continuation with ContinueWith
- part 6 - Recurring jobs and cron expressions
In the previous post I’ve written about why I think the ability to schedule tasks for later execution is a fundamental technical feature, but also a must have from business’ point of view. We are passed the whys, so let’s get to the hows. The answer is simple - Hangfire. I’ve written about it here, here and here, so yeah, you guessed it, I like it. Hangfire is an amazing library. It has shown it’s value in my pet project (cookit.pl) and in a huge ERP system that we are building at work, where we replaced Quartz.NET with it and never looked back.
Why do I like it so much?
It enables: - to fire(enqueue) and forget a job:
BackgroundJob.Enqueue(() => Console.WriteLine("Simple!"));`
- to schedule a one time job using a cron expression
BackgroundJob.Schedule(() => Console.WriteLine("Reliable!"), TimeSpan.FromDays(7));
- and to schedule a recurring job also with a cron expression
RecurringJob.AddOrUpdate(() => Console.WriteLine("Transparent!"), Cron.Daily)
A side note: Cron expressions allow to express almost any time span, and using them is a standard in most task scheduling cases (Quartz.NET, Unix, TeamCity to name a few). There is a good Wikipedia page explaining the syntax. Think of them as regular expressions for time.
I personally fell in love with the simplicity of this API, and especially with the fact that it takes a function to execute, not an object. Although this examples are simple lambdas Hangfire allows to schedule executing methods on almost any objects, but this is a topic for another post. Probably the next one:)
The key point in procrastinating tasks is to not do them now, but to have certainty that they will be executed. That is why persisting jobs in a database is a key feature. And Hangfire has a hand of stores to persist in: - SQL Server (nuget package) - PostgreSql (nuget package) - Redis (nuget package, but only in paid pro version)
And configuring any of them is as simple as scheduling a job:
JobStorage.Current = new SqlServerStorage("HangfireConnectionString")
3. Job execution
Persisting a job in a database gives the possibility for another process to execute it. And Hangfire does just that. Of course the process executing the job has to have all the assemblies needed to execute the code, but this is just another argument for not having everything jammed into one project. Hangfire can be hosted by a: - console application - Windows service - IIS website
And configuring it is as easy as scheduling a job:
using (var server = new BackgroundJobServer())
Console.WriteLine("Hangfire Server started. Press any key to exit...");
For me the ability to have a graphic interface to see current jobs, queues, errors and processing servers was a must-have when choosing a library for a simple reason - I needed it and didn’t want to write it myself. And Hangfire has just that:
This was a glimpse of what this library can do. It’s not always bells and whistles, but I’ve never regretted choosing it can’t imagine working without the ability to schedule tasks. In the next post - a better look into jobs.