13

如果作业引发异常,我已经搜索了有关如何在一定时间后重新触发作业的答案。我看不到任何简单的方法来做到这一点。

如果我这样设置触发器:

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

MyJob 看起来像这样:

public class MyJob : IJob
{
    public void Execute(JobExecutionContext context)
    {
        var service = new service();


        try
        {
            service.Download();
        }
        catch (Exception)
        {
            throw;
        }

    }
}

如果 service.Download() 调用引发某种异常,如何在 15 分钟后触发重新触发/重新触发?

4

4 回答 4

23

实际上,没有必要像 LeftyX 描述的那样创建一个新的 JobDetail。您可以只安排一个从当前上下文连接到 JobDetail 的新触发器。

public void Execute(JobExecutionContext context) {
    try {
        // code
    } catch (Exception ex) {
        SimpleTriggerImpl retryTrigger = new SimpleTriggerImpl(Guid.NewGuid().ToString());      
        retryTrigger.Description = "RetryTrigger";
        retryTrigger.RepeatCount = 0;
        retryTrigger.JobKey = context.JobDetail.Key;   // connect trigger with current job      
        retryTrigger.StartTimeUtc = DateBuilder.NextGivenSecondDate(DateTime.Now, 30);  // Execute after 30 seconds from now
        context.Scheduler.ScheduleJob(retryTrigger);   // schedule the trigger

        JobExecutionException jex = new JobExecutionException(ex, false);
        throw jex;
    }
}

这比创建新的 JobDetail 更不容易出错。希望有帮助。

于 2012-11-07T13:47:51.737 回答
9

我认为正确的答案是使用 JobListener 重试工作,如下所述:http: //thecodesaysitall.blogspot.cz/2012/03/quartz-candy-part-1.html

在此解决方案中,您将重试逻辑与 Job 本身分开,因此可以重用。

如果您按照此处其他回复中的建议在作业中实施重试逻辑,则必须在每个作业中再次实施。

编辑:根据 Ramanpreet Singh 的说明,可以在这里找到更好的解决方案: https ://blog.harveydelaney.com/quartz-job-exception-retrying/

于 2013-09-26T11:10:37.353 回答
6

我认为您唯一的选择是捕获错误并告诉 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;  
        }
    }
}

你可以在这里这里找到一些信息。

更新

我做了一些测试,似乎您可以在正在执行的作业中安排一个新的触发器。
你可以尝试这样的事情:

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);     
        }
    }
}
于 2012-06-06T11:42:37.643 回答
0
// don't forget to use @PersistJobDataAfterExecution without it, the jobExecutionContext will reset the value of count.     

SimpleTriggerImpl retryTrigger = new SimpleTriggerImpl();
    retryTrigger.setName("jobname");
    retryTrigger.setRepeatCount(0);
    retryTrigger.setJobKey(jobExecutionContext.getJobDetail().getKey());
    final Calendar cal = getCalendarInstance();
    cal.add(Calendar.MINUTE, 1); //retry after one minute
    retryTrigger.setStartTime(cal.getTime());
    try {
        jobExecutionContext.getScheduler().scheduleJob(retryTrigger);   // schedule the trigger
    } catch (SchedulerException ex) {
        logger.error("something went wrong", ex); 
    }
    JobExecutionException e2 = new JobExecutionException("retrying...");
    e2.refireImmediately();
    throw e2;
于 2019-01-16T12:57:27.470 回答