Refire quartz.net trigger after 15 minutes if job fails with exception

后端 未结 4 1454
心在旅途
心在旅途 2020-12-29 10:44

I have searched for an answer on how to retrigger a job after a ceratin amount of time, if the job throws an exception. I cannot see any simple way of doing this.

if

相关标签:
4条回答
  • 2020-12-29 11:24
    // 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;
    
    0 讨论(0)
  • 2020-12-29 11:26

    Actually, its not necessary to create a new JobDetail like described by LeftyX. You can just schedule a new trigger that is connected to the JobDetail from the current context.

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

    This is less error prone than creating a new JobDetail. Hope that helps.

    0 讨论(0)
  • 2020-12-29 11:27

    I think that the right answer is to use JobListener to retry a job as described here: http://thecodesaysitall.blogspot.cz/2012/03/quartz-candy-part-1.html.

    You separate retry logic from Job itself in this solution, so it can be reused.

    If you implement retry logic in job as suggested in another replies here, it must be implemented again in every job.

    Edit: According to the Ramanpreet Singh note better solution can be found here: https://blog.harveydelaney.com/quartz-job-exception-retrying/

    0 讨论(0)
  • 2020-12-29 11:33

    I think the only option you have is to trap the error and tell Quartz.net to refire immediately:

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

    You can find some info here and here.

    UPDATE:

    I did some tests and it seems that you can schedule a new trigger inside an executing job.
    You can try something like this:

    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);     
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题