Haraldur
Haraldur

Reputation: 227

Hangfire duplicates jobs on server restart

So we have an .NET Core API which uses hangfire as a task scheduler.

On startup, our API starts the following functions :

public void CreateTasks()
{
    /* DATABASE TASKS */
    SyncDatabaseTask();

    /* SMS TASKS */
    SendSmsTask();

}

public void SendSmsTask()
{
    var taskId = BackgroundJob.Schedule(() => _smsService.SendSms(), TimeSpan.FromMinutes(30));
    BackgroundJob.ContinueWith(taskId, () => SendSmsTask());
}

This creates the job SendSmsTask in Hangfire on startup and does not start a second job until the first one has been completed.

The issue that we just noticed however is that whenever our API reboots (server update for example) the existing jobs are still running and news jobs are being added.

So we would like to remove all scheduled or running jobs on startup.

I've looked through the documentation (http://docs.hangfire.io/en/latest/) but couldn't really find a solution for this issue.

Upvotes: 0

Views: 2801

Answers (4)

Alexander
Alexander

Reputation: 1263

HF 1.7.28

For me deleting Enqueued jobs like suggested did not work. Instead, I had to use the following:

hangfireMonitor.Queues().ToList().ForEach(x => x.FirstJobs.Where(j => j.Value.InEnqueuedState).ToList().ForEach(x => BackgroundJob.Delete(x.Key)));

Upvotes: 0

cancmrt
cancmrt

Reputation: 139

If you still interest Pieter Alberts solution.

Some little changes on that.

If you use old code and you have old job in db, you will get Format Exception.

In //RecurringJobs section you have to change line like this:

JobStorage.Current.GetConnection().GetRecurringJobs().ForEach(xx => RecurringJob.RemoveIfExists(xx.Id));

TL;DR

Old Code:

private void RemoveAllHangfireJobs()
    {
        var hangfireMonitor = JobStorage.Current.GetMonitoringApi();

        //RecurringJobs
        JobStorage.Current.GetConnection().GetRecurringJobs().ForEach(xx => BackgroundJob.Delete(xx.Id));

        //ProcessingJobs
        hangfireMonitor.ProcessingJobs(0, int.MaxValue).ForEach(xx => BackgroundJob.Delete(xx.Key));

        //ScheduledJobs
        hangfireMonitor.ScheduledJobs(0, int.MaxValue).ForEach(xx => BackgroundJob.Delete(xx.Key));

        //EnqueuedJobs
        hangfireMonitor.Queues().ToList().ForEach(xx => hangfireMonitor.EnqueuedJobs(xx.Name,0, int.MaxValue).ForEach(x => BackgroundJob.Delete(x.Key)));
    }

New Code:

private void RemoveAllHangfireJobs()
    {
        var hangfireMonitor = JobStorage.Current.GetMonitoringApi();

        //RecurringJobs
        JobStorage.Current.GetConnection().GetRecurringJobs().ForEach(xx => RecurringJob.RemoveIfExists(xx.Id)); // this line changed!

        //ProcessingJobs
        hangfireMonitor.ProcessingJobs(0, int.MaxValue).ForEach(xx => BackgroundJob.Delete(xx.Key));

        //ScheduledJobs
        hangfireMonitor.ScheduledJobs(0, int.MaxValue).ForEach(xx => BackgroundJob.Delete(xx.Key));

        //EnqueuedJobs
        hangfireMonitor.Queues().ToList().ForEach(xx => hangfireMonitor.EnqueuedJobs(xx.Name,0, int.MaxValue).ForEach(x => BackgroundJob.Delete(x.Key)));
    }

PS Edit: My Hangfire version is 1.7.9 and using Hangfire.PostgreSql

Upvotes: 1

Lucas Lima
Lucas Lima

Reputation: 9

            //Start Hangfire Server
        var varJobOptions = new BackgroundJobServerOptions();
        varJobOptions.ServerName = "job.fiscal.io";
        varJobOptions.WorkerCount = Environment.ProcessorCount * 10;
        app.UseHangfireServer(varJobOptions);
        app.UseHangfireDashboard("/jobs", new DashboardOptions {
            Authorization = new[] { new clsHangFireAuthFilter() }
        });
        //Remove Duplicte HangFire Server
        var varMonitoringApi = JobStorage.Current.GetMonitoringApi();
        var varServerList = varMonitoringApi.Servers().Where(r => r.Name.Contains("job.fiscal.io"));
        foreach( var varServerItem in varServerList) {
            JobStorage.Current.GetConnection().RemoveServer(varServerItem.Name);
        }

Upvotes: 0

Pieter Alberts
Pieter Alberts

Reputation: 879

This should solve your problem, just note that this is untested.

    private void RemoveAllHangfireJobs()
    {
        var hangfireMonitor = JobStorage.Current.GetMonitoringApi();

        //RecurringJobs
        JobStorage.Current.GetConnection().GetRecurringJobs().ForEach(xx => BackgroundJob.Delete(xx.Id));

        //ProcessingJobs
        hangfireMonitor.ProcessingJobs(0, int.MaxValue).ForEach(xx => BackgroundJob.Delete(xx.Key));

        //ScheduledJobs
        hangfireMonitor.ScheduledJobs(0, int.MaxValue).ForEach(xx => BackgroundJob.Delete(xx.Key));

        //EnqueuedJobs
        hangfireMonitor.Queues().ToList().ForEach(xx => hangfireMonitor.EnqueuedJobs(xx.Name,0, int.MaxValue).ForEach(x => BackgroundJob.Delete(x.Key)));
    }

Upvotes: 3

Related Questions