GrailsのQuartzプラグインを使っている場合に、ジョブスケジューリングを動的に変更したいときがあります*1。
一見、こちらにある「Dynamic Jobs Scheduling」にある方法で変更できそうにも思えますが、ジョブ名やトリガー名を与えることができないインターフェースであることからもわかるように、いずれも新規にジョブおよびトリガーを作成します。つまり既存のジョブが止まらずに、新たなスケジューリングのジョブが増えるだけなので、既存のジョブのスケジューリングを変更することはできません。
それを行うには、Grails Quartzプラグインのインターフェースを経由せずに、自力でQuartzの機能を使って更新する必要があります。
class MyJob { static triggers = { cron name: 'myTrigger', cronExpression: "0/5 * * * * ?" } def execute(context) { println "do my job!" } }
こんなジョブがgrails-app/jobs以下で定義されているという前提で、
以下が動的にスケジュールを変更するコード例(Grailsのコントローラ中を想定)。
void setCronExpression(String expression) { def scheduler = grailsApplication.mainContext.getBean("quartzScheduler") def trigger = scheduler.getTrigger("myTrigger", "GRAILS_TRIGGERS") if (!trigger instanceof CronTrigger) { println "this type of trigger is not supported" return } scheduler.pauseTrigger("myTrigger", "GRAILS_TRIGGERS") trigger.cronExpression = expression scheduler.rescheduleJob("myTrigger", "GRAILS_TRIGGERS", trigger) //トリガを置き代える scheduler.resumeTrigger("myTrigger", "GRAILS_TRIGGERS") } def interval1sec() { setCronExpression("0/1 * * * * ?") render "ABC" }
cronExpressionを変更するだけでは駄目で、変更が反映されるためには、Scheduler#rescheduleJobを必要があります。
これはCronTriggerの場合ですが、他の場合もおそらく同様でしょう。
(追記) ↓について、「*1" cronスケジュール定義を外部config.groovyに書けばいい」というブコメを@nobeansからもらいましたが(とんきゅー)、cronスケジュール定義はjobs/*Job.groovyに書くしかないようなので(これが間違い?)、例えばquartzとしての設定ファイル「grails-app/conf/quartz.properties」に書いた上で外部化すれば良いという話かな。もしそうなら、その上で、外部化設定ファイルのリロードプラグインとかを使って、onConfigChangeイベントを発生させ、そのハンドラがスケジューラを更新するようになっているか、プラグインがそう処理するかの問題だけど…今度試してみよう。ただ、grails-app/conf/quartz.propertiesで設定するぐらいなら、Grails Quartzプラグインを使う意味はどこに…という気もする。以下で指摘しているのはGrails Quartzプラグインの問題「Grails QueartzプラグインがWapperとして簡易すぎる」なのだから。