2012-06-05 11 views
11

Szukałem odpowiedzi na pytanie, jak ponownie wykonać zadanie po upływie określonego czasu, jeśli zadanie zgłasza wyjątek. Nie widzę żadnego prostego sposobu robienia tego.Refire quartz.net trigger po 15 minutach, jeśli zadanie zakończyło się niepowodzeniem z wyjątkiem:

jeśli mogę ustawić spust się tak:

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

I MyJob wyglądać następująco:

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


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

    } 
} 

jak mogę zrobić spust do refire/Retrigger po tam nie ma 15 minut, jeśli wywołanie service.Download() wywołuje jakiś wyjątek?

Odpowiedz

6

Myślę, że jedynym rozwiązaniem jest mieć do wyłapania błędów i powiedzieć Quartz.net natychmiast refire:

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

Można znaleźć jakieś info here i here.

UPDATE:

Zrobiłem kilka testów i wydaje się, że można zaplanować nowy spust wewnątrz wykonującego zadania.
Można spróbować czegoś takiego:

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

Tak. Przeczytałem to, ale nie jest to dobre rozwiązanie, ponieważ mogłoby to potencjalnie oznaczać, że będzie odnawiał się wiele tysięcy razy (a nawet miliony razy). Ale miło widzieć, że doszliście do tego wniosku. – mslot

+0

@mslot: Zaktualizowałem swoją odpowiedź. – LeftyX

+0

Dzięki: D Miałem taki sam pomysł, ale po raz pierwszy używam kwarcu, więc nie byłem pewien, czy mógłbyś użyć kontekstu. – mslot

19

Właściwie, to nie jest konieczne, aby utworzyć nowy JobDetail jak opisane przez LeftyX. Możesz tylko zaplanować nowy wyzwalacz, który jest podłączony do JobDetail z bieżącego kontekstu.

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

Jest to mniej podatne na błędy niż tworzenie nowej karty JobDetail. Nadzieja, która pomaga.

5

Myślę, że właściwą odpowiedzią jest użycie JobListener do ponowienia zadania, jak opisano tutaj: http://thecodesaysitall.blogspot.cz/2012/03/quartz-candy-part-1.html.

Użytkownik oddziela logikę od samego zadania w tym rozwiązaniu, dzięki czemu może być ponownie użyty.

Jeśli zaimplementujesz logikę ponowną w zadaniu, jak zasugerowano w innych odpowiedziach tutaj, musi ona zostać zaimplementowana ponownie w każdym zadaniu.

+2

Zgadzam się. Przyjęta odpowiedź to rozwiązanie "pas i szelki" (co jest w porządku, jeśli potrzebujesz tylko wykonać zadanie), ale dodanie "słuchacza do powtórzenia" może być lepszym (i bardziej wielokrotnego użytku) rozwiązaniem długoterminowym. Nie sądzę, że wdrożenie jest idealne, ale jest to dobre miejsce na rozpoczęcie ... Źródło na GitHub: https://github.com/malmgren80/Quartz.Candy –