2011-11-23 3 views
5

私は月の最初の日の真夜中に特定のタスクを実行するために、Quartz with Springを使用しています。私はサーバーの日付を&に設定して、月の最後の日に11:59に設定し、サーバーを起動して12:00になるとタスクが実行されるのを観察してテストしましたが、サーバーは(何らかの理由で)月の初めに真夜中に実行されていない可能性があります。欠けているクォーツジョブを実行する

私はQuartzでの失火処理がこれを気にかけていると思っていましたが、おそらく私はそれを誤解していますか?

どのように私はこれを処理することができるかもしれないかについて助言をいただけますか?私は本当にすべての 'x'秒/分/時間を実行し、私がそれを避けることができる場合、私はジョブを実行する必要があるかどうかを確認するジョブを作成しないことを好むだろう。

なぜ私はQuartz関連のログ情報が表示されないのか不思議ですが、それは副次的な問題です。ここで

は、タスクのための私の春の構成です:

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

答えて

2

MISFIRE_INSTRUCTION_FIRE_ONCE_NOWはあなたが言及した目的のためであり、あなたがサーバ(群)の運転停止が疑われる場合、あなたは間違いなく、JVMのメモリのうち、あなたの仕事を永続化する必要があり(例:RAMJobStoreの代わりにJDBCJobStoreを使用する)。

RAMJobStoreは高速かつ軽量ですが、プロセスが終了するとすべてのスケジューリング情報が失われます。 http://quartz-scheduler.org/documentation/quartz-2.x/configuration/ConfigRAMJobStore

JDBCJobStore

は、リレーショナル・データベース内のスケジューリング情報(ジョブ、トリガおよびカレンダー)を格納するために使用されます。

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

それに役立つ願っています。

0

私もサーバーの再起動時に最後のscheuledジョブを実行したいという問題に直面しました。

これは、私がトリガーの1つの時間間隔に戻って、次の発射時間であったであろうものを計算することであることが判明した解決策です。全てのトリガを反復することにより、トリガが過去に発射されたはずの最も最近の時間を決定することができる。


それぞれの発射間隔を計算します。

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

は、過去のインターバルまで1時間のために、次の発射時間を探す:

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

を使用している場合は、そのIを発見しましたCronTriggerこれは過去の火災の時間を求めるのを防ぎます。この問題を回避するために、私は開始時間を変更するので、上記のスニペットは次のようになります。私は「

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

:トリガーのすべての過去に最も最近であるものを見つけて

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 

反復読者にこれをヘルパーメソッドまたはクラスにリファクタリングするための練習として残します。実際に上記のアルゴリズムをサブクラス化されたデリゲートトリガーで使用して、前回の発火時刻でソートされたセットに配置します。