Our client processes a lot of dossier creation each day from different sources from within each of their departments. All these dossiers are created within their own applications and are then sent to an application we developed for them. They wanted to automate this creation process and prevent as much load peaks as possible during business hours. The solution was a background process that they can run whenever they want.
For this use case (and because here at Foreach we have no fear of tools we do not know yet) we looked at a nice, light, easy to use framework called Hangfire. This framework would allow us to create and manage background tasks without having to create a background service on the server.
Hangfire gives the developer an easy way to create different kinds of tasks, one of them the task that we needed for our “dossier creation” process, a simple Fire and Forget job.
What is it?
Hangfire adds an extra layer on top of your code. You pass calls to Hangfire which stores it into its own database. Hangfire then manages the calls for you, so you do not have to worry about the work you’ve enqueued being blocking. If it fails, it even retries it automatically in the way you configured.
Hangfire also gives you a nice clean dashboard where you can look at your enqueued jobs and, if you so wish, manage them manually. It truly is a fun little framework.
Hangfire allows you to synchronously enqueue a job in your code, and executes this code asynchronously through a first come, first serve queue.
A few examples of the types of jobs:
- Fire-and-forget (like we needed)
- Recurring (like a cron job)
- Continuations of other jobs
The jobs you’ve enqueued will be saved inside a persistent storage of your own choosing. They support many popular storages, relational or document based.
The benefit is that, even during random shutdowns, your jobs are safe and ready to be handled when the application has restarted.
What if something went wrong and my job throws an exception? Nothing to worry about really. Hangfire has its own automatic retry mechanism that retries your jobs for you in an intelligent manner.
Hangfire uses workers to handle the tasks, you define the number of workers you want and they share the queue, running the tasks on a first come first serve basis. Hangfire’s UI is itself protected by an API key (a GUID which you define) and accessible from /hangfire if you have the API key.
Implementing Hangfire proved to be easy. By following the documentation we created a configuration file for Hangfire that looks like this.
You then wire it into your services with a single line of code:
Configure your app. We created a Hangfire Extensions class where we just grouped the configuration methods.
Our extension class:
That is all for configuration, your Hangfire is now ready to be used. This is also quite simple and we will provide an example.
We have an API that allows for external systems to update an with the help of Hangfire. We created a controller action that you can send the employee info to and it will update this accordingly
The Controller only has this:
The service creates the job:
_jobClient is your injected Hangfire Client to which you pass the job. CreateJobForEvent has all the business logic you wish to see executed when the task is started.
It all comes together in the nice UI where you can see your enqueued, executed, and failed jobs, and monitor their progress. The below screenshot has been taken directly from the hangfire documentation site as an example.
And an example of how your failed job shows up (also taken from the hangfire documentation site)
One of the most fun parts for us was that after implementing it, we got to see our tasks in the Hangfire Dashboard. This gives us a visual representation of our tasks, the attempts, the retries, and the number of . It also gives a brief code snippet of the job it will perform, which is just dandy for when you want to debug.
The only real disadvantage as far as we saw was that we had to make the methods public because Hangfire serializes the method for it’s use. This is of course not something you wish to do all the time because your method is then exposed to all others that want to use them.
As a final word we want to express our love for this little framework. So much so that is has become a commonly used component in our projects. We now use it in three different APIs. It’s easy to use, it’s clean and it has a simple UI. This makes it a reliable framework that most of our clients can definitely reap the benefits from.
For more info visit the site of hangfire itself at https://www.hangfire.io/ or ask your questions in the comments.