Prevent a Hangfire job from running when it is already active
I'm writing this blog post about Hangfire as a reminder for my future myself because I keep forgetting the syntax to do this, and perhaps this can help you as well. To give a small version of what Hangfire is and does to those who are not familiar with it, it's a NET library that allows you to easily run background (fire and forget) jobs, delayed jobs, and recurring jobs.
An easy way to perform background processing in .NET and .NET Core applications. No Windows Service or separate process required. Backed by persistent storage.
What I really enjoy about Hangfire is that it also comes with a useful dashboard to make the jobs visual, and you also get a screen with the failed jobs with a retry functionality.
I particularly use Hangfire for its recurring background job capabilities, which is a job that uses a CRON expression to run some logic on a regular interval. It's also about this that I want to write a small reminder. My use case is that I have a recurring job that runs frequently and I want to prevent it from running if its previous job is still active. Ideally, the job runs as soon as possible. Using Hangfire the lowest interval is every minute, which can be configured using the * * * * * (at every minute) CRON expression .
In 90% of the cases that doesn't become a problem because the recurring job normally takes a few seconds, and thus finishes on time before the new job is due. But due to circumstances, a higher amount of work, a slower network, or other hiccups, the job can take longer than a minute, and thus a new job is queued up before the previous one finishes. This can all lead to issues.
To prevent Hangfire from running a new job while the previous one is still running, you can use the DisableConcurrentExecution attribute. This attribute queues up the next job but doesn't run it until the previous one is finished.
To use it, add the
DisableConcurrentExecution attribute on top of the method that is invoked by Hangfire.
The attribute also accepts a parameter that configures the duration until a timeout is thrown.
I appreciate it if you would support me if have you enjoyed this post and found it useful, thank you in advance.