web-dev-qa-db-fra.com

Quartz CronTrigger - Prochain feu

J'utilise l'installation Quartz CronTrigger pour analyser les chaînes de format de planification cron afin de déterminer le moment où un travail spécifique doit être exécuté. Je n'utilise pas réellement Quartz pour planifier le travail.

Il existe une méthode dans CronTrigger appelée getFireTimeAfter (Date) qui indique la prochaine fois que le travail sera lancé après la date donnée. Cela fonctionne bien lorsque la date fournie est maintenant ou dans le futur. Mais cela ne semble pas fonctionner si la date est dans le passé. 

Date currTime = new Date();
CronTrigger tr = new CronTrigger();
tr.setCronExpression("0 0 23 3,18 * ? *");
Date nextFireAt = tr.getFireTimeAfter(currTime);
System.out.println("Reference time: " + currTime);
System.out.println("Next fire after reference time: " + nextFireAt);

Ce qui est un programme cron pour tirer à 23h00 les 3 et 18 de chaque mois. Ainsi, par exemple, si je faisais cela aujourd'hui (le 11 août), je verrais:

Reference time: Thu Aug 11 10:04:25 MDT 2011
Next fire after reference time: Thu Aug 18 23:00:00 MDT 2011

Mais si je mets la date de référence au passé, cela me donne la même heure du prochain feu. 

Reference time: Wed Dec 31 17:00:00 MST 1969
Next fire after reference time: Thu Aug 18 23:00:00 MDT 2011

Je m'attendais à ce que le résultat soit:

Reference time: Wed Dec 31 17:00:00 MST 1969
Next fire after reference time: Wed Aug 3 23:00:00 MDT 2011

Est-ce que la méthode n'est tout simplement pas destinée à fonctionner de cette façon ou est-ce que je fais quelque chose de mal?

Merci!

17
cambo

Qu'est-ce que vous voulez vraiment utiliser l'objet CronExpression directement, pas le CronTrigger. Comme vous l'avez découvert, il ne calculera pas les temps d'exécution précédents dans le passé ... mais CronExpression le fera!

CronExpression a la méthode suivante: getNextValidTimeAfter. Voici ce que vous voulez.

32
Jason Clawson

Au printemps, vous pourrez suivre la même approche que celle utilisée dans leurs tests d'intégration. CronTriggerTests

CronTrigger trigger = new CronTrigger();
trigger.setCronExpression("0 0 23 3,18 * ? *");
SimpleTriggerContext triggerContext = new SimpleTriggerContext();
triggerContext.update(null, null, new Date());
Date nextFireAt = trigger.nextExecutionTime(triggerContext);
3
ibai

La méthode CronTrigger.getFireTimeAfter() a un mécanisme de protection pour empêcher que le temps spécifié ne soit dans le passé. 

Cela peut être contourné en appelant setStartTime firth avec le temps passé que vous évaluez. Ensuite, l'appel à getFireTimeAfter devrait revenir avec un résultat valide.

1
darrenmc

C'est un peu bizarre mais le mécanisme de protection existe. Aucune idée pourquoi l'équipe Quartz a cette vérification. Le test ci-dessous ne réussit que si j'ajoute une heure à la nxtDay (nxtDay = nxtTrigger.Value.DateTime.AddHours(1);)

var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");

//FREQUENCY OF SECONDS 
var reccurrence = new Reccurrence
{
    StartTime = new TimeSpan(9, 0, 0),
    StopTime = new TimeSpan(11, 0, 0),
    WeekDay = "MON-Sun",
    TimeZoneInfo = timeZoneInfo,
    Frequency = 15,
    FrequencyUnit = FrequencyUnit.Seconds
};

var autoPublishDetail = new AutoPublishJobDetail("TestReccurence_Seconds", _log, null, reccurrence);
var trigger = autoPublishDetail.GetDailyTrigger();
var nxt = trigger.GetNextFireTimeUtc();

var jobSeconds = JobBuilder.Create().WithIdentity(new JobKey("TestReccurence_Seconds")).OfType(typeof(AutoPublishJob)).Build();

_scheduler.ScheduleJob(jobSeconds, trigger);

//This job sud run 4 times in a 60 secs and from 9 am to 11 am (Span of 3 hrs including 11 onwards to 11:59:59)
//Total runs = 4 x 60 x 3 = 720
var today = DateTime.Now;
var tomorrow = today.AddDays(1);
DateTime? nxtDay = new DateTime(tomorrow.Year, tomorrow.Month, tomorrow.Day);

int jobCnt = 0;
do
{
    var nxtTrigger = trigger.GetFireTimeAfter(nxtDay.Value);

    if (nxtTrigger.Value.Year.Equals(today.AddDays(2).Year) && nxtTrigger.Value.Month.Equals(today.AddDays(2).Month) && nxtTrigger.Value.Day.Equals(today.AddDays(2).Day))
        break;

    jobCnt++;
    nxtDay = nxtTrigger.Value.DateTime.AddHours(1);

} while (true);

Assert.AreEqual(720, jobCnt);
0
user3603550

Selon le Quartz doc :

Retourne l'heure à laquelle le CronTrigger va se déclencher, après l'heure indiquée

"Fera le feu" implique "dans le futur". C'est-à-dire que la prochaine fois que la CronTrigger sera déclenchée, elle n'est pas dans le passé et les dates antérieures ne sont pas renvoyées.

Je ne sais pas exactement ce que vous essayez de réaliser, mais ces méthodes vous intéressent la nuit:

  • getPreviousFireTime (): Retourne le dernier déclenchement du déclencheur
  • getTimeBefore (): renvoie l'heure à laquelle le déclencheur a été activé avant une date donnée (fonctionne dans le passé) - Remarque: celui-ci semble être pour l'instant inapplémenté.
0
Vivien Barousse