Refire quartz.net триггер через 15 минут, если сбой работы с исключением
Я искал ответ о том, как повторить задание после определенного количества времени, если задание выдает исключение. Я не вижу никакого простого способа сделать это.
если я установил свой триггер следующим образом:
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;
}
}
}
как я могу заставить триггер refire/retrigger после того, как прошло 15 минут, если вызов службы .Download() вызывает какое-то исключение?
Ответы
Ответ 1
Я думаю, что единственный вариант, который у вас есть, - это уловить ошибку и сказать 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;
}
}
}
Вы можете найти здесь здесь и здесь.
UPDATE
Я сделал несколько тестов, и кажется, что вы можете назначить новый триггер внутри исполняемого задания.
Вы можете попробовать что-то вроде этого:
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);
}
}
}
Ответ 2
Собственно, его не нужно создавать новый JobDetail, как описано LeftyX. Вы можете просто запланировать новый триггер, который подключен к 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. Надеюсь, что это поможет.
Ответ 3
Я думаю, что правильный ответ - использовать JobListener, чтобы повторить работу, как описано здесь: http://thecodesaysitall.blogspot.cz/2012/03/quartz-candy-part-1.html.
В этом решении вы отделяете логику повторных попыток от самого Job, чтобы ее можно было использовать повторно.
Если вы реализуете логику повтора в задании, как это было предложено в других ответах, это должно быть реализовано снова в каждом задании.
Изменение: Согласно записке Раманприта Сингха, лучшее решение можно найти здесь: https://blog.harveydelaney.com/quartz-job-exception-retry/
Ответ 4
// 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;