Triggers 如果作业异常失败,请在15分钟后重新启动quartz.net触发器
我一直在寻找一个答案,如果某个工作抛出异常,如何在一段时间后重新触发该工作。我看不出有什么简单的方法可以做到这一点 如果我像这样设置触发器:Triggers 如果作业异常失败,请在15分钟后重新启动quartz.net触发器,triggers,quartz.net,Triggers,Quartz.net,我一直在寻找一个答案,如果某个工作抛出异常,如何在一段时间后重新触发该工作。我看不出有什么简单的方法可以做到这一点 如果我像这样设置触发器: JobDetail job = new JobDetail("Download catalog", null, typeof(MyJob)); job .Durable = true; Trigger trigger= TriggerUtils.MakeDailyTrigger(12, 0); trigger.StartTimeUtc = DateTime
JobDetail job = new JobDetail("Download catalog", null, typeof(MyJob));
job .Durable = true;
Trigger trigger= TriggerUtils.MakeDailyTrigger(12, 0);
trigger.StartTimeUtc = DateTime.UtcNow;
trigger.Name = "trigger name";
scheduler.ScheduleJob(job , trigger);
public class MyJob : IJob
{
public void Execute(JobExecutionContext context)
{
var service = new service();
try
{
service.Download();
}
catch (Exception)
{
throw;
}
}
}
public class MyJob : IJob
{
public void Execute(JobExecutionContext context)
{
var service = new service();
try
{
service.Download();
}
catch (Exception ex)
{
JobExecutionException qe = new JobExecutionException(ex);
// qe.RefireImmediately = true; // this job will refire immediately
// throw qe;
OnErrorScheduleJob(context);
}
}
private void OnErrorScheduleJob(JobExecutionContext context)
{
var jobOnError = context.Scheduler.GetJobDetail("ONERRORJOB", "ERROR");
if (jobOnError == null)
{
JobDetail job = new JobDetail("ONERRORJOB", "ERROR", typeof(MyJob));
job.Durable = false;
job.Volatile = false;
job.RequestsRecovery = false;
SimpleTrigger trigger = new SimpleTrigger("ONERRORTRIGGER",
"ERROR",
DateTime.UtcNow.AddMinutes(15),
null,
1,
TimeSpan.FromMinutes(100));
context.Scheduler.ScheduleJob(job, trigger);
}
}
}
我的工作是这样的:
JobDetail job = new JobDetail("Download catalog", null, typeof(MyJob));
job .Durable = true;
Trigger trigger= TriggerUtils.MakeDailyTrigger(12, 0);
trigger.StartTimeUtc = DateTime.UtcNow;
trigger.Name = "trigger name";
scheduler.ScheduleJob(job , trigger);
public class MyJob : IJob
{
public void Execute(JobExecutionContext context)
{
var service = new service();
try
{
service.Download();
}
catch (Exception)
{
throw;
}
}
}
public class MyJob : IJob
{
public void Execute(JobExecutionContext context)
{
var service = new service();
try
{
service.Download();
}
catch (Exception ex)
{
JobExecutionException qe = new JobExecutionException(ex);
// qe.RefireImmediately = true; // this job will refire immediately
// throw qe;
OnErrorScheduleJob(context);
}
}
private void OnErrorScheduleJob(JobExecutionContext context)
{
var jobOnError = context.Scheduler.GetJobDetail("ONERRORJOB", "ERROR");
if (jobOnError == null)
{
JobDetail job = new JobDetail("ONERRORJOB", "ERROR", typeof(MyJob));
job.Durable = false;
job.Volatile = false;
job.RequestsRecovery = false;
SimpleTrigger trigger = new SimpleTrigger("ONERRORTRIGGER",
"ERROR",
DateTime.UtcNow.AddMinutes(15),
null,
1,
TimeSpan.FromMinutes(100));
context.Scheduler.ScheduleJob(job, trigger);
}
}
}
如果service.Download()调用引发某种异常,我如何在15分钟后触发refire/retrigger?我认为您唯一的选择是捕获错误并告诉Quartz.net立即重新填充:
public class MyJob : IJob
{
public void Execute(JobExecutionContext context)
{
var service = new service();
try
{
service.Download();
}
catch (Exception ex)
{
JobExecutionException qe = new JobExecutionException(ex);
qe.RefireImmediately = true; // this job will refire immediately
throw qe;
}
}
}
你可以找到一些信息和建议
更新:
我做了一些测试,您似乎可以在正在执行的作业中安排一个新触发器。您可以尝试以下方法:
JobDetail job = new JobDetail("Download catalog", null, typeof(MyJob));
job .Durable = true;
Trigger trigger= TriggerUtils.MakeDailyTrigger(12, 0);
trigger.StartTimeUtc = DateTime.UtcNow;
trigger.Name = "trigger name";
scheduler.ScheduleJob(job , trigger);
public class MyJob : IJob
{
public void Execute(JobExecutionContext context)
{
var service = new service();
try
{
service.Download();
}
catch (Exception)
{
throw;
}
}
}
public class MyJob : IJob
{
public void Execute(JobExecutionContext context)
{
var service = new service();
try
{
service.Download();
}
catch (Exception ex)
{
JobExecutionException qe = new JobExecutionException(ex);
// qe.RefireImmediately = true; // this job will refire immediately
// throw qe;
OnErrorScheduleJob(context);
}
}
private void OnErrorScheduleJob(JobExecutionContext context)
{
var jobOnError = context.Scheduler.GetJobDetail("ONERRORJOB", "ERROR");
if (jobOnError == null)
{
JobDetail job = new JobDetail("ONERRORJOB", "ERROR", typeof(MyJob));
job.Durable = false;
job.Volatile = false;
job.RequestsRecovery = false;
SimpleTrigger trigger = new SimpleTrigger("ONERRORTRIGGER",
"ERROR",
DateTime.UtcNow.AddMinutes(15),
null,
1,
TimeSpan.FromMinutes(100));
context.Scheduler.ScheduleJob(job, trigger);
}
}
}
实际上,没有必要像LeftyX所描述的那样创建新的JobDetail。您只需计划一个从当前上下文连接到JobDetail的新触发器
public void Execute(作业执行上下文){
试一试{
//代码
}捕获(例外情况除外){
SimpleTriggerImpl retryTrigger=newSimpleTriggerImpl(Guid.NewGuid().ToString());
retryTrigger.Description=“retryTrigger”;
retryTrigger.RepeatCount=0;
retryTrigger.JobKey=context.JobDetail.Key;//将触发器与当前作业连接
retryTrigger.StartTimeUtc=DateBuilder.NextGivenSecondDate(DateTime.Now,30);//从现在起30秒后执行
context.Scheduler.ScheduleJob(retryTrigger);//计划触发器
JobExecutionException jex=新的JobExecutionException(ex,false);
扔杰克斯;
}
}
这比创建新的JobDetail更不容易出错。希望这会有所帮助。我认为正确的答案是使用JobListener重试此处描述的作业: 在此解决方案中,您可以将重试逻辑与作业本身分离,以便可以重用 若您在作业中实现了重试逻辑(如此处其他答复中所建议的),则必须在每个作业中再次实现该逻辑 编辑: 根据Ramanpreet Singh注释,可以找到更好的解决方案:
是的。我读过这篇文章,但它不是一个好的解决方案,因为它可能意味着它将重复数千次(甚至数百万次)。但很高兴看到您得出了这个结论。谢谢:D我也有同样的想法,但这是我第一次使用石英,所以我不确定您是否可以使用上下文。@mslot:没问题。很高兴我帮了忙,我同意。公认的答案是“安全带和支架”解决方案(如果您只需要完成工作,这很好),但添加“重试侦听器”可能是一个更好(并且更可重用)的长期解决方案。我不认为实现是完美的,但这是一个很好的开始。。。GitHub上的资料来源:链接的解决方案在这里得到了改进:@DavidKirkland你的解决方案棒极了。干净利落