Recurring job with original start date passed in

I looked through the forum but couldn’t see a similar topic. Is there any easy way to set up a recurring job that will encapsulate its intended start date?

I need this for a daily evening job that will look for sets of records that had expired/need reminders that day so if the job fails, I need to re-run it for its original day rather than the re-run day. I looked at using the JobFilterAttribute and OnPerforming which does have the original date but I couldn’t see a way to actually pass that through to the executing method.

I can get around it by storing a ‘LastRun’ date in the db and just using that but I would rather use Hangfire to ensure the job is run in the state it would have been if it succeeded.

Would passing the date as an argument work? I think I’m doing something similar where the job you queue up in Hangfire passes a date argument into another method. Hangfire serializes the arguments, that even when a retry is executed the same date is used:

I don’t think it will unless I’m misunderstanding because that will wrap the date that the recurring job was set up rather than this instance it fired e.g.

Set up job 10/08/2015 using RecurringJob.AddOrUpdate(() => _notification.SendNotifications(DateTime.Now),Cron.Daily(17,00);
It will serialise the date into the job def so when it gets called the next day (11/08/2015) then it’ll still be passing in 10/08/2015 as a parameter.

What I would like is that when the cron fires for the job on 11/08/2015, it passes in 11/08/2015 as the date but if it fails that night and I retry that particular job (rather than kick off the reocurring job fresh) the next night (12/08/2015) then it passes in 11/08/2015.

Internally the recurring job scheduler is just creating a new job at every “instant” in your configured schedule:

When you retry an “instant” job that was created by the scheduler, you’re actually just setting the job’s state back to EnqueuedState which includes a timestamp:

If you look in the database (Assuming SQL storage) each “instant” job has a series of states in the Hangfire.State table so you can retrieve the first EnqueuedState record for your job:

SELECT * FROM [HangFire].[State] WHERE JobId = 1141 ORDER BY CreatedAt DESC

You can use this call to retrieve this data programatically: (Sadly the “CreatedData” of the state is not exposed, but a Data property is which includes the EnqueuedAt property from the EnqueuedState.)

How about having the recurring job only schedule a fire-and-forget job for the current day (pass the current date as an argument)?
If the fire-and-forget job for any given day fails, it will be retried with the same argument as on the first try…

1 Like