Hangfire: Changing cron expression of recurring job causes immediate execution

Created on 14 Nov 2016  路  7Comments  路  Source: HangfireIO/Hangfire

Reported on the discussion forum, see this topic. Here is a description:

Hangfire has a recurring job with a cron expression (should fire each day at 01:00 UTC):

0 1 * * *

This job was updated at 15:00 UTC with new cron expression (should fire each day at 02:00 UTC):

0 2 * * *

It led to immediate execution of the recurring job at 15:00 UTC. Later the job was beeing executed correctly every day at 02:00 UTC

This occurs because RecurringJobScheduler looks at LastExecution field to decide when a job will be executed. It's necessary to run missed recurring jobs after Hangfire server was down for some time .

In the case described above RecurringJobScheduler decided at 15:00 UTC that there was missed job which had to be performed at 02:00.

I think before RecurringJobScheduler see at 'LastExecution' field it should see at 'LastCronChangedAt' field (this field doesn't exist yet).

It can lead not to run some missed recurring jobs hardly ever. Example:

  1. Hangfire server is down from 01:00 UTC to 17:00 UTC
  2. There is a recurring job which should fire each day at 02:00 UTC (cron 0 2 * * *)
  3. The recurring job was updated ad 07:00 UTC with new cron expreesion 0 3 * * *. So it should fire at 03:00 UTC every day.

In this case there is missed job which had to be performed at 02:00 UTC. But I think it's not as bad as the behavior described above. Moreover in my opinion it's not bug but feature.

core bug

Most helpful comment

A temporary solution (to who don't care about the last execution time) could be just removing the job if it already exists before "updating" it, this way we ensure that the last execution time after updating will be null:
RecurringJob.RemoveIfExists(Id);
RecurringJob.AddOrUpdate(Id, () => RunJob(), cron, timezone);

All 7 comments

A temporary solution (to who don't care about the last execution time) could be just removing the job if it already exists before "updating" it, this way we ensure that the last execution time after updating will be null:
RecurringJob.RemoveIfExists(Id);
RecurringJob.AddOrUpdate(Id, () => RunJob(), cron, timezone);

Just experienced this in production and it almost created an uncomfortable situation. Please don't skip doing a bugfix even though there's a workaround! Thanks!

I am also looking for a solution on this. I am not sure why this simple bug is taking so long. I would have hopped a little better turnaround for a product that was made commercial.

Any solution?
Almost charged a bunch of clients in the wrong day because of it.

I'm really sorry for your time loss, but there was no appropriate solution for this problem in versions 1.6.X and below, where recurring job scheduler was fetching all the recurring jobs to see whether it's time to run them. I even was thinking about adding a new method to handle this case, but it was too ugly, as with deleting/creating a recurring job to update it.

But with changes introduced in version 1.7.0 it's finally possible now to fix the behavior by changing four lines, which will be there with version 1.7.8 this week.

Closing the issue as 1.7.8 was released.

Hello, we upgraded to version 1.7.18 and got same behaviour of the dashboard. Job got triggered instantly after a change in schedule and when dashboard accessed.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

nsnail picture nsnail  路  3Comments

cottsak picture cottsak  路  3Comments

shorbachuk picture shorbachuk  路  4Comments

JvanderStad picture JvanderStad  路  3Comments

vikramjb picture vikramjb  路  3Comments