Frage an quartz.net, triggers – Lösen Sie den quartz.net-Trigger nach 15 Minuten aus, wenn der Job mit Ausnahme fehlschlägt

13

Ich habe nach einer Antwort gesucht, wie ein Job nach einer bestimmten Zeit erneut ausgelöst werden kann, wenn der Job eine Ausnahme auslöst. Ich kann keinen einfachen Weg sehen, dies zu tun.

wenn ich meinen Trigger so einstelle:

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

Und MyJob sieht so aus:

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


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

    }
}

Wie kann ich den Trigger aktivieren / deaktivieren, nachdem 15 Minuten vergangen sind, wenn der service.Download () -Aufruf eine Ausnahmebedingung auslöst?

Deine Antwort

4   die antwort
8

dass die richtige Antwort darin besteht, JobListener zu verwenden, um einen Job wie hier beschrieben erneut zu versuchen:http://thecodesaysitall.blogspot.cz/2012/03/quartz-candy-part-1.html.

In dieser Lösung trennen Sie die Wiederholungslogik von Job selbst, sodass sie wiederverwendet werden kann.

Wenn Sie die Wiederholungslogik in Job implementieren, wie in anderen Antworten hier vorgeschlagen, muss sie in jedem Job erneut implementiert werden.

Edit: Laut dem Ramanpreet Singh-Hinweis kann eine bessere Lösung gefunden werdenHier: https://blog.harveydelaney.com/quartz-job-exception-retrying/

Die verknüpfte Lösung wurde hier verbessert:blog.harveydelaney.com/quartz-job-exception-retrying Ramanpreet Singh
Genau. Die akzeptierte Antwort ist eine "Gürtel und Hosenträger" -Lösung (die in Ordnung ist, wenn Sie nur die Arbeit erledigen müssen), aber das Hinzufügen eines "Wiederholungs-Listeners" ist möglicherweise eine bessere (und wiederverwendbarere) langfristige Lösung. Ich denke nicht, dass die Implementierung perfekt ist, aber es ist ein guter Ort, um zu beginnen ... Quelle auf GitHub:github.com/malmgren80/Quartz.Candy David Kirkland
6

die einzige Möglichkeit, die Sie haben, besteht darin, den Fehler abzufangen und Quartz.net mitzuteilen, dass es sofort kündigt:

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

Sie können einige Informationen findenHier undHier.

AKTUALISIEREN:

Ich habe einige Tests durchgeführt und es scheint, dass Sie einen neuen Trigger in einem ausgeführten Job planen können.
Sie können so etwas ausprobieren:

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);     
        }
    }
}
@mslot: Ich habe meine Antwort aktualisiert. LeftyX
Danke: D Ich hatte die gleiche Idee, aber dies ist das erste Mal, dass ich Quarz verwende. Ich war mir nicht sicher, ob Sie den Kontext verwenden können. mslot
Ja. Dies habe ich gelesen, aber es ist keine gute Lösung, da es potenziell bedeuten könnte, dass es viele tausend Mal (oder sogar millionenfach) ausfällt. Aber schön zu sehen, dass Sie zu diesem Schluss gekommen sind. mslot
@mslot: kein problem. Froh, dass ich geholfen habe. LeftyX
0
// 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;
19

einen neuen JobDetail zu erstellen, wie von LeftyX beschrieben. Sie können einfach einen neuen Trigger planen, der aus dem aktuellen Kontext mit dem JobDetail verbunden ist.

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

Dies ist weniger fehleranfällig als das Erstellen eines neuen JobDetails. Hoffentlich hilft das.

Verwandte Fragen