我遇到了Quartz和RescheduleJob
函数的问题。
我有一个电子邮件处理器队列,并且正在为未处理的电子邮件进行重新计划。电子邮件具有重试计数(每一个),如果电子邮件发送过程失败,则重试计数会增加,并且电子邮件已入队。每次处理器启动时,都会处理队列中的电子邮件。
问题事实是,在应用启动时,新的计划作业会在最短的时间(1分钟)内出现在具有不同实例的情况下,并且看起来并不相同。
在文档中说:
使用给定的密钥删除(删除)Quartz.ITrigger,并存储 新赠与-必须与同一工作相关联(新 触发器必须指定作业名称和组)-但是,新 触发器不必与旧触发器具有相同的名称。
但是在我的日志中却是:
2018-06-21 10:03:21,201 [DefaultQuartzScheduler_Worker-1] INFO Services.BaseService [(null)] - Email Send error. Contact Form | To:esddaada@test.com Subject: Thank You for Contacting. Email moved to Send Queue.
2018-06-21 10:04:05,177 [DefaultQuartzScheduler_Worker-1] WARN Services.EmailJob [(null)] - EmailJob Time elapsed updated to 2 mins.
2018-06-21 10:04:07,874 [DefaultQuartzScheduler_Worker-2] INFO Services.BaseService [(null)] - Email Send error. Contact Form | To:esddaada@test.com Subject: Thank You for Contacting Us. Email moved to Send Queue.
2018-06-21 10:04:59,900 [DefaultQuartzScheduler_Worker-2] WARN Services.EmailJob [(null)] - EmailJob Time elapsed updated to 4 mins.
2018-06-21 10:05:03,595 [DefaultQuartzScheduler_Worker-3] INFO Services.BaseService [(null)] - Email Send error. Contact Form | To:esddaada@test.com Subject: Thank You for Contacting Us. Email moved to Send Queue.
2018-06-21 10:05:08,439 [DefaultQuartzScheduler_Worker-3] WARN Services.EmailJob [(null)] - EmailJob Time elapsed updated to 6 mins.
2018-06-21 10:05:11,155 [DefaultQuartzScheduler_Worker-4] INFO Services.BaseService [(null)] - Email Send error. Contact Form | To:esddaada@test.com Subject: Thank You for Contacting Us. Email moved to Send Queue.
2018-06-21 10:05:18,871 [DefaultQuartzScheduler_Worker-4] WARN Services.EmailJob [(null)] - EmailJob Time elapsed updated to 8 mins.
2018-06-21 10:05:22,539 [DefaultQuartzScheduler_Worker-5] INFO Services.BaseService [(null)] - Email Send error. Contact Form | To:esddaada@test.com Subject: Thank You for Contacting Us. Email moved to Send Queue.
2018-06-21 10:05:22,551 [DefaultQuartzScheduler_Worker-5] ERROR Services.EmailJob [(null)] - Email on Queue Reach max 6 send retry Times! Application: To:esddaada@test.com Subject:Thank You for Contacting Us.
这是我的代码:
public static void StartEmailJob() // scheduler called on Application_Start()
{
var scheduler = StdSchedulerFactory.GetDefaultScheduler();
var emailJob = JobBuilder.Create<EmailJob>().Build();
var trigger = TriggerBuilder.Create()
.WithIdentity("EmailJob", "group1")
// .StartAt(DateTimeOffset.Now.AddMinutes(1))
.WithSimpleSchedule(sh => sh
.WithIntervalInMinutes(RetryInterval)
.RepeatForever())
.Build();
scheduler.ScheduleJob(emailJob, trigger);
scheduler.Start();
}
[DisallowConcurrentExecution]
public class EmailJob : IJob
{
public void Execute(IJobExecutionContext context)
{
var retryCount = 5;
var emailsQueue = context.Emails;
if (emailsQueue.Any(ml => ml.RetryCount < retryCount))
{
var emails = emailsQueue .Where(ml => ml.RetryCount < retryCount);
var count = emails.FirstOrDefault().RetryCount;
foreach (var email in emails)
{
if (!EmailService.SendEmail(email, out string error))
{
if (email.RetryCount >= retryCount)
{
Logger.Error($"Email on Queue Reach max {retryCount} send retry Times!");
}
}
else
{
//remove email from queue
}
}
try
{
RescheduleJob(context, count, true);
}
catch (Exception exc)
{
Logger.Error("EmailJob RescheduleJob Error!", exc);
}
}
else
{
try
{
RescheduleJob(context, 0, true);
}
catch (Exception exc)
{
Logger.Error("EmailJob RescheduleJob Error!", exc);
}
}
}
}
public void RescheduleJob(IJobExecutionContext jobContext, int retryCount, bool startsNow)
{
var retryInterval = 5;
var scheduler = StdSchedulerFactory.GetDefaultScheduler();
// get the trigger
var intervalReminder = (retryCount == 0 ? 1 : retryCount) * retryInterval;
var triggerBuilder = jobContext.Trigger.GetTriggerBuilder();
//crerates a new trigger with the old one
var newTrigger = triggerBuilder.WithSimpleSchedule(s => s
.WithIntervalInMinutes(intervalReminder)
.RepeatForever())
.Build();
if (newTrigger is ISimpleTrigger simpleTrigger)
{
if (jobContext.JobInstance is ISimpleTrigger trigger)
(newTrigger as ISimpleTrigger).TimesTriggered = trigger.TimesTriggered;
}
// reschedule the job with a new trigger
scheduler.RescheduleJob(jobContext.Trigger.Key, newTrigger);
Logger.Warn($"EmailJob Time elapsed updated to {intervalReminder} mins.");
}
}
奇怪的是,一段时间后,当重试时间用尽时,它按预期工作。为什么?我不知道。
有人可以帮助我吗? 谢谢。
答案 0 :(得分:0)
最后,我将代码更改为使用另一列,并存储下一个日期重试间隔。我删除了RescheduleJob
,并且当我检查
var retryIntervals = new[] { 15, 25, 45, 60, 93, 110, 150 };
var emails = emailsQueue .Where(ml => ml.RetryCount < retryCount && ml.NextTimeRetry <= DateTimeOffset.UtcNow);
我也更改了此部分,以考虑到必须更改重试时间
if (!EmailService.SendEmail(email, out string error))
{
email.NextTimeRetry = DateTimeOffset.UtcNow.AddMinutes(retryIntervals[email.RetryCount]);
if (email.RetryCount >= retryCount)
{
Logger.Error($"Email on Queue Reach max {retryCount} send retry Times!");
}
}
目前没有人回答这个问题,但是对人们知道如何处理这个问题很有帮助。