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你的解决方案棒极了。干净利落