2012-06-05 5 views
11

Ho cercato una risposta su come riattivare un lavoro dopo un certo periodo di tempo, se il lavoro genera un'eccezione. Non riesco a vedere nessun modo semplice per farlo.Refire trigger quartz.net dopo 15 minuti se il lavoro non riesce con eccezione

se ho impostato il mio grilletto in questo modo:

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

E MyJob simile a questa:

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


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

    } 
} 

come faccio a rendere il grilletto per refire/retrigger dopo c'è andato 15 minuti se la chiamata service.Download() genera una sorta di eccezione?

risposta

6

Credo che l'unica possibilità che hai è quella di intercettare l'errore e dire Quartz.net a refire subito:

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

si possono trovare alcune informazioni here e here.

UPDATE:

Ho fatto alcuni test e sembra che è possibile pianificare un nuovo trigger all'interno di un lavoro di esecuzione.
Si può provare qualcosa di simile:

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

Sì. Questo l'ho letto, ma non è una buona soluzione, perché potrebbe significare che potrebbe rigirarsi molte migliaia di volte (o addirittura rifirare milioni di volte). Ma è bello vedere che sei arrivato a questa conclusione. – mslot

+0

@mslot: ho aggiornato la mia risposta. – LeftyX

+0

Grazie: D Avevo la stessa idea, ma questa è la prima volta che utilizzo il quarzo, quindi non ero sicuro di poter usare il contesto. – mslot

19

In realtà, non è necessario creare un nuovo JobDetail come descritto da LeftyX. È possibile pianificare un nuovo trigger collegato a JobDetail dal contesto corrente.

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

Questo è meno soggetto a errori rispetto alla creazione di un nuovo JobDetail. Spero possa aiutare.

5

Penso che la risposta corretta sia usare JobListener per riprovare un lavoro come descritto qui: http://thecodesaysitall.blogspot.cz/2012/03/quartz-candy-part-1.html.

Si separa la logica di riprova da Job stesso in questa soluzione, quindi può essere riutilizzata.

Se si implementa la logica di riprova nel lavoro come suggerito in altre risposte qui, deve essere implementato nuovamente in ogni lavoro.

+2

Sono d'accordo. La risposta accettata è una soluzione "cintura e bretelle" (che va bene se hai solo bisogno di portare a termine il lavoro), ma l'aggiunta di un "ripetitore di ascolto" potrebbe essere una soluzione migliore (e più riutilizzabile) a lungo termine. Non penso che l'implementazione sia perfetta, ma è un buon punto di partenza ... Source su GitHub: https://github.com/malmgren80/Quartz.Candy –