2012-06-05 10 views
11

He buscado una respuesta sobre cómo volver a disparar un trabajo después de una determinada cantidad de tiempo, si el trabajo arroja una excepción. No puedo ver ninguna forma simple de hacer esto.Refiera el disparador de quartz.net después de 15 minutos si falla el trabajo con la excepción

si fijo mi gatillo de esta manera:

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

Y MyJob tener este aspecto:

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


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

    } 
} 

cómo hago el gatillo para refire/se vuelven a disparar después de que se ha ido 15 minutos si la llamada a service.Download() arroja algún tipo de excepción?

Respuesta

6

Creo que la única opción que tienes es para interceptar el error y decirle a Quartz.net refire inmediato:

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

se pueden encontrar algunos información here y here.

ACTUALIZACIÓN:

Hice algunas pruebas y parece que se puede programar un nuevo disparador dentro de un trabajo de ejecución.
Usted puede intentar algo como esto:

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í. Esto lo he leído, pero no es una buena solución, porque podría significar que se refinaría miles de veces (o incluso refinaría millones de veces). Pero es bueno ver que has llegado a esta conclusión. – mslot

+0

@mslot: He actualizado mi respuesta. – LeftyX

+0

Gracias: D Tuve la misma idea, pero esta es la primera vez que uso cuarzo, así que no estaba seguro de poder utilizar el contexto. – mslot

19

En realidad, no es necesario crear una nueva JobDetail como se describe por leftyx. Puede programar un nuevo disparador que esté conectado a JobDetail desde el contexto actual.

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

Esto es menos propenso a errores que la creación de un nuevo JobDetail. Espero que ayude.

5

Creo que la respuesta correcta es utilizar JobListener para volver a intentar un trabajo como se describe aquí: http://thecodesaysitall.blogspot.cz/2012/03/quartz-candy-part-1.html.

Se separa la lógica de reintento del trabajo en esta solución, por lo que se puede reutilizar.

Si implementa la lógica de reintento en el trabajo como se sugiere en otras respuestas aquí, debe implementarse nuevamente en cada trabajo.

+2

Estoy de acuerdo. La respuesta aceptada es una solución de "cinturón y abrazaderas" (que está bien si solo tiene que hacer el trabajo), pero agregar un "oyente de reintentos" podría ser una solución mejor (y más reutilizable) a largo plazo. No creo que la implementación sea perfecta, pero está bien comenzar ... Fuente en GitHub: https://github.com/malmgren80/Quartz.Candy –

Cuestiones relacionadas