Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hangfire get last execution time

I'm using hangfire 1.5.3. In my recurring job I want to call a service that uses the time since the last run. Unfortunately the LastExecution is set to the current time, because the job data was updated before executing the job.

Job

public abstract class RecurringJobBase
{
    protected RecurringJobDto GetJob(string jobId)
    {
        using (var connection = JobStorage.Current.GetConnection())
        {
            return connection.GetRecurringJobs().FirstOrDefault(p => p.Id == jobId);
        }
    }

    protected DateTime GetLastRun(string jobId)
    {
        var job = GetJob(jobId);

        if (job != null && job.LastExecution.HasValue)
        {

            return job.LastExecution.Value.ToLocalTime();
        }

        return DateTime.Today;
    }
}

public class NotifyQueryFilterSubscribersJob : RecurringJobBase
{
    public const string JobId = "NotifyQueryFilterSubscribersJob";
    private readonly IEntityFilterChangeNotificationService _notificationService;

    public NotifyQueryFilterSubscribersJob(IEntityFilterChangeNotificationService notificationService)
    {
        _notificationService = notificationService;
    }

    public void Run()
    {
        var lastRun = GetLastRun(JobId);
        _notificationService.CheckChangesAndSendNotifications(DateTime.Now - lastRun);
    }
}

Register

RecurringJob.AddOrUpdate<NotifyQueryFilterSubscribersJob>(NotifyQueryFilterSubscribersJob.JobId, job => job.Run(), Cron.Minutely, TimeZoneInfo.Local);

I know, that it is configured as minutely, so I could calculate the time roughly. But I'd like to have a configuration independent implementation. So my Question is: How can I implement RecurringJobBase.GetLastRun to return the time of the previous run?

like image 371
Sven-Michael Stübe Avatar asked Feb 04 '16 15:02

Sven-Michael Stübe


1 Answers

To address my comment above, where you might have more than one type of recurring job running but want to check previous states, you can check that the previous job info actually relates to this type of job by the following (although this feels a bit hacky/convoluted).

If you're passing the PerformContext into the job method than you can use this:

var jobName = performContext.BackgroundJob.Job.ToString();
var currentJobId = int.Parse(performContext.BackgroundJob.Id);
JobData jobFoundInfo = null;

using (var connection = JobStorage.Current.GetConnection()) {
    var decrementId = currentJobId;
    while (decrementId > currentJobId - 50 && decrementId > 1) { // try up to 50 jobs previously
        decrementId--;
        var jobInfo = connection.GetJobData(decrementId.ToString());
        if (jobInfo.Job.ToString().Equals(jobName)) { // **THIS IS THE CHECK**
            jobFoundInfo = jobInfo;
            break;
        }
    }
    if (jobFoundInfo == null) {
       throw new Exception($"Could not find the previous run for job with name {jobName}");
    }
    return jobFoundInfo;
}
like image 167
WheretheresaWill Avatar answered Sep 23 '22 19:09

WheretheresaWill