Pytanie w sprawie triggers, quartz.net – Wywołaj wyzwalacz quartz.net po 15 minutach, jeśli zadanie zakończy się niepowodzeniem z wyjątkiem

13

Szukałem odpowiedzi na pytanie, jak ponownie wywołać zadanie po upływie czasu ceratyny, jeśli zadanie zgłasza wyjątek. Nie widzę żadnego prostego sposobu na to.

jeśli ustawię mój wyzwalacz w ten sposób:

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

A MyJob wygląda tak:

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


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

    }
}

Jak sprawić, aby wyzwalacz powrócił / wyzwalał po 15 minutach, jeśli wywołanie service.Download () wywoła jakiś wyjątek?

Twoja odpowiedź

4   odpowiedź
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;
8

że właściwą odpowiedzią jest skorzystanie z JobListener, aby ponowić zadanie, jak opisano tutaj:http://thecodesaysitall.blogspot.cz/2012/03/quartz-candy-part-1.html.

W tym rozwiązaniu oddzielasz logikę ponawiania od samego Joba, aby można go było ponownie wykorzystać.

Jeśli zaimplementujesz logikę ponownej próby w pracy, jak zasugerowano w innych odpowiedziach tutaj, musi ona zostać zaimplementowana ponownie w każdym zadaniu.

Edytuj: Według Ramanpreet Singh można znaleźć lepsze rozwiązanietutaj: https://blog.harveydelaney.com/quartz-job-exception-retrying/

Zgadzam się. Przyjętą odpowiedzią jest rozwiązanie „pas i szelki” (co jest w porządku, jeśli wystarczy wykonać zadanie), ale dodanie „ponownej próby słuchacza” może być lepszym (i bardziej użytecznym) rozwiązaniem długoterminowym. Nie sądzę, aby implementacja była idealna, ale warto zacząć ... Źródło na GitHub:github.com/malmgren80/Quartz.Candy David Kirkland
Powiązane rozwiązanie zostało poprawione tutaj:blog.harveydelaney.com/quartz-job-exception-retrying Ramanpreet Singh
6

że jedyną dostępną opcją jest złapanie błędu i nakazanie Quartz.net natychmiastowego wycofania:

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żesz znaleźć informacjetutaj itutaj.

AKTUALIZACJA:

Zrobiłem kilka testów i wydaje się, że możesz zaplanować nowy wyzwalacz w wykonywanym zadaniu.
Możesz 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);     
        }
    }
}
Tak. Przeczytałem to, ale nie jest to dobre rozwiązanie, ponieważ może potencjalnie oznaczać, że będzie się powtarzać wiele tysięcy razy (a nawet milion razy). Ale miło widzieć, że doszedłeś do tego wniosku. mslot
@mslot: zaktualizowałem swoją odpowiedź. LeftyX
Dzięki: D Miałem taki sam pomysł, ale po raz pierwszy używam kwarcu, więc nie byłem pewien, czy można użyć kontekstu. mslot
@mslot: nie ma problemu. Cieszę się, że pomogłem. LeftyX
19

jak opisano w LeftyX. Możesz po prostu 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 aplikacji JobDetail. Mam nadzieję, że to pomoże.

Powiązane pytania