Hangfire 在服务器重启时复制作业

Hangfire duplicates jobs on server restart

所以我们有一个 .NET Core API,它使用 hangfire 作为任务调度程序。

启动时,我们的 API 启动以下功能:

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());
}

这会在启动时在 Hangfire 中创建作业 SendSmsTask,并且在第一个作业完成之前不会启动第二个作业。

然而,我们刚刚注意到的问题是,每当我们的 API 重新启动(例如服务器更新)时,现有作业仍然 运行 并且正在添加新作业。

所以我们想在启动时删除所有计划的或 运行 个作业。

我已查看文档 (http://docs.hangfire.io/en/latest/),但无法真正找到解决此问题的方法。

这应该可以解决您的问题,请注意这是未经测试的。

    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)));
    }
            //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);
        }

如果您仍然对 Pieter Alberts 解决方案感兴趣。

一些小改动。

如果您使用旧代码并且在数据库中有旧工作,您将得到格式异常。

//RecurringJobs 部分,您必须像这样更改行:

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

TL;DR

旧代码:

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)));
    }

新代码:

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 编辑: 我的 Hangfire 版本是 1.7.9 并使用 Hangfire.PostgreSql