2012-06-05 65 views
11

如果作業引發異常,我已經搜索瞭如何在角色消耗一段時間後重新觸發作業的答案。我看不到任何這樣做的簡單方法。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; 
     } 

    } 
} 

如何使扳機,重燒/再觸發那裏走了15分鐘如果後service.Download()調用會引發某種異常?

回答

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

你可以找到一些信息herehere

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);  
     } 
    } 
} 
+0

是的。我已經閱讀過,但這不是一個好的解決方案,因爲它可能意味着它將會重複數千次(甚至是數百萬次)。但很高興看到你已經得出這個結論。 – mslot

+0

@mslot:我已經更新了我的答案。 – LeftyX

+0

感謝:D我有同樣的想法,但這是我第一次使用石英,所以我不確定你是否可以使用上下文。 – mslot

19

其實,它不是必要建立一個新的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更不容易出錯。希望有所幫助。

5

我認爲正確的答案是使用JobListener重試一個工作,如下所述:http://thecodesaysitall.blogspot.cz/2012/03/quartz-candy-part-1.html

您在此解決方案中將作業本身的重試邏輯分開,因此可以重複使用。

如果按照另一個回覆中的建議在作業中實施重試邏輯,則必須在每項作業中重新執行該作業。

+2

我同意。被接受的答案是一個「腰帶和大括號」解決方案(如果你只是需要完成工作,這很好),但添加一個「重試監聽器」可能是一個更好的(也是更可重用的)長期解決方案。我不認爲這個實現是完美的,但它是開始的好地方...來源於GitHub:https://github.com/malmgren80/Quartz.Candy –

相關問題