2011-11-23 20 views
5

Uso il quarzo con Spring per eseguire un'attività specifica a mezzanotte del primo giorno del mese. Ho testato il lavoro impostando la data del server & in modo che sia 11:59 l'ultimo giorno del mese, avviando il server e osservando l'esecuzione dell'attività quando si passa alle 12:00, ma sono preoccupato per i casi in cui il il server (per qualsiasi motivo) potrebbe non essere in esecuzione a mezzanotte del primo del mese.Esecuzione di un lavoro al quarzo mancante

Avevo dato per scontato che la gestione dei malfunzionamenti in Quartz avrebbe avuto importanza per questo, ma forse mi sbaglio su questo?

Qualcuno mi può consigliare su come potrei essere in grado di gestirlo? Preferirei davvero non creare un lavoro che esegua "x" secondi/minuti/ore e verificare se ho bisogno di eseguire il lavoro se posso evitarlo.

Sono anche curioso di sapere perché non vedo alcuna informazione di registrazione relativa al quarzo, ma questo è un problema secondario.

Ecco la mia configurazione a molla per l'attività:

<bean id="schedulerService" class="com.bah.pams.service.scheduler.SchedulerService"> 
    <property name="surveyResponseDao" ref="surveyResponseDao"/> 
    <property name="organizationDao" ref="organizationDao"/> 
</bean> 

<bean name="createSurveyResponsesJob" class="org.springframework.scheduling.quartz.JobDetailBean"> 
    <property name="jobClass" value="com.bah.pams.service.scheduler.jobs.CreateSurveyResponsesJob"/> 
    <property name="jobDataAsMap"> 
     <map> 
      <entry key="schedulerService" value-ref="schedulerService"/> 
     </map> 
    </property> 
</bean> 
<!-- Cron Trigger --> 
<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean"> 
    <property name="jobDetail" ref="createSurveyResponsesJob"/> 
    <property name="cronExpression" value="0 0 0 1 * ? *"/> 
    <!--if the server is down at midnight on 1st of month, run this job as soon as it starts up next --> 
    <property name="misfireInstructionName" value="MISFIRE_INSTRUCTION_FIRE_ONCE_NOW"/> 
</bean> 

<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> 

    <property name="autoStartup" value="true"/> 

    <property name="quartzProperties"> 
     <props> 
      <prop key="org.quartz.jobStore.class">org.quartz.simpl.RAMJobStore</prop> 
      <prop key="org.quartz.jobStore.misfireThreshold">60000</prop> 
     </props> 
    </property> 
    <property name="jobDetails"> 
     <list> 
      <ref bean="createSurveyResponsesJob"/> 
     </list> 
    </property> 

    <property name="triggers"> 
     <list> 
      <ref bean="cronTrigger"/> 
     </list> 
    </property> 
</bean> 

risposta

2

MISFIRE_INSTRUCTION_FIRE_ONCE_NOW è per lo scopo che lei ha citato e se si sospetta un arresto del server (s) che si dovrebbe assolutamente persistere i lavori dalla memoria JVM (es .: utilizzando un JDBCJobStore invece di un RAMJobStore).

RAMJobStore è veloce e leggero, ma tutte le informazioni di pianificazione vengono perse al termine del processo.

http://quartz-scheduler.org/documentation/quartz-2.x/configuration/ConfigRAMJobStore

JDBCJobStore viene utilizzata per memorizzare informazioni di pianificazione (lavoro, trigger e calendari) all'interno di un database relazionale.

http://quartz-scheduler.org/documentation/quartz-2.x/configuration/ConfigJobStoreTX

Speranza che aiuta.

0

Anche io ho affrontato il problema di voler eseguire l'ultimo lavoro programmato su un riavvio del server.

Questa è la soluzione che ho trovato è di tornare indietro di un intervallo di tempo per il trigger e calcolare quale sarebbe stato il prossimo tempo di accensione. Attraverso l'iterazione di tutti i trigger, è possibile determinare il momento più recente in cui un trigger deve essere stato attivato in passato.


calcolare l'intervallo tra ogni cottura:

Date nextFireTime = trigger.getNextFireTime(); 
Date subsequentFireTime = trigger.getFireTimeAfter(nextFireTime); 
long interval = subsequentFireTime.getTime() - nextFireTime.getTime(); 

Trova il tempo di cottura successiva per un tempo fino a intervallo in passato:

Date previousPeriodTime = new Date(System.currentTimeMillis() - interval); 
Date previousFireTime = trigger.getFireTimeAfter(previousPeriodTime); 

Ho scoperto che se si utilizza a CronTrigger questo ti impedisce di chiedere un tempo di fuoco in passato.Per ovviare a questo modifico l'ora di inizio, in modo che il pezzo di codice sopra diventa:

Date originalStartTime = trigger.getStartTime(); // save the start time 
Date previousPeriodTime = new Date(originalStartTime.getTime() - interval); 
trigger.setStartTime(previousPeriodTime); 
Date previousFireTime = trigger.getFireTimeAfter(previousPeriodTime); 
trigger.setStartTime(originalStartTime); // reset the start time to be nice 

scorrere tutti i trigger e trovare quello che è più recente nel passato:

for (String groupName : scheduler.getTriggerGroupNames()) { 
    for (String triggerName : scheduler.getTriggerNames(groupName)) { 
     Trigger trigger = scheduler.getTrigger(triggerName, groupName); 
     // code as detailed above... 
     interval = ... 
     previousFireTime = ... 
    } 
} 

I' Lasceremo come esercizio al lettore il refactoring in metodi o classi di aiuto. In realtà uso l'algoritmo di cui sopra in un trigger delegante sottoclasse che poi inserisco in un set ordinato per tempi di attivazione precedenti.

Problemi correlati