【问题标题】:Hangfire duplicates jobs on server restartHangfire 在服务器重启时重复作业
【发布时间】:2019-01-08 21:29:37
【问题描述】:

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

在启动时,我们的 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/),但无法真正找到解决此问题的方法。

【问题讨论】:

    标签: c# .net-core scheduled-tasks hangfire


    【解决方案1】:

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

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

    【讨论】:

    • 测试了代码,这确实解决了我的问题。谢谢:)
    【解决方案2】:
                //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);
            }
    

    【讨论】:

      【解决方案3】:

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

      对此进行了一些小改动。

      如果你使用旧代码并且你在 db 中有旧工作,你会得到 Format Exception。

      //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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-06-04
        • 2017-03-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-08-27
        • 2019-12-25
        相关资源
        最近更新 更多