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
所以我们有一个 .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