[play1-jobs]ジョブの使い方

  playframework1

概要

HTTPリクエストとは関係なく処理を行ないたいときに、非同期ジョブ機能がある。(もちろんHTTPリクエストをトリガにして実行することもできる)

準備

play.jobs.jobクラスを継承したクラスを用意する。(javaのバージョンが許せば無名クラスでも構わない)

public void doJob()メソッドを実装し、行ないたい処理を書く。
処理結果をTクラスで返したいときは、play.jobs.job<T>を継承し、public T doJobWithResult()メソッドを実装する。

実行する

すぐに実行

インスタンスを生成し、now(), in(), afterRequest() のいずれかのメソッドを実行する。

  • now()は、即時実行。
  • in(int)は、遅延実行。秒で指定する。
  • in(String)も、遅延実行。こちらは @Everyと同じ書式。
  • afterRequest()は、HTTPリクエスト中に意味を持つ。現在実行中のアクションが終了してから実行する。
    例えば、JPAでsave()、コミット後にジョブを実行したいときに有効。(play1.3から実装された)

runメソッドというのも存在するが使用してはいけない。面倒でもnow()メソッドを使うこと。

いずれのメソッドも、Promiseオブジェクトを戻り値に持つので、play.mvc.Controller.await(int) を用いてジョブの終了まで、リクエストをサスペンド状態にすることができる。サスペンド状態にすると、コネクションが解放されるので、次のリクエストを処理することができる。

応答に長時間かかるリクエストであっても、コネクションを占有しないで済むとされる。

実行完了まで待つ方法

Promise job = new MyJob().now();
job.get();

job.get()でジョブ終了まで待つ。Promise<V>だったら、Vが返却される。

アプリケーション開始時に実行

ジョブクラスに対し、@OnApplicationStartアノテーションを付与すると、アプリケーション開始時にジョブが実行される。処理結果は残らない。

アノテーションのasyncプロパティはデフォルトはfalseになっている。async=falseの場合、ジョブ処理が終了するまでアプリケーションは開始しない。
逆に、async=true に設定すると、バックグラウンドで動作する。

細かいこと

  • afterApplicationStart()イベント内より実行される。
  • 起動時にインスタンスが一度だけ生成され、スケジュール管理に残り続けるので勝手に消滅しない。
  • DEVモードでは最初のリクエストを受けたときに実行。
  • PRODモードではサービス起動時に実行。

アプリケーション終了時に実行

ジョブクラスに対し、@OnApplicationStopアノテーションを付与すると、アプリケーション終了時に実行される。
play.Play.stop()が実行されたときなので必ず実行されるとは限らない

onApplicationStop()イベント内より実行される。
インスタンスは終了時に生成される。

一定間隔で実行

ジョブクラスに対し、@Everyアノテーションを付与すると、引数に指定した間隔でジョブが実行される。

単位接尾辞例(意味)
d3d (3日ごと)
時間h1h (1時間ごと)
mn5mn (5分ごと)
s15s (15秒ごと)

引数に上記の間隔文字列ではなく、”cron.hoge” と指定すると、application.conf [cron.hoge] に設定した値を参照する。”never”とすると周期実行されないので、アプリケーションIDによって動作のON/OFFを分けることができる。

@Every("cron.hoge")
public class MyJob extends Job { ...
# %prodの時だけ実行する
cron.hoge=never
%prod.cron.hoge=3h

インスタンスは起動時に一度だけ生成され、アプリケーション実行中はずっと残りつづける。

定時に実行

ジョブクラスに対し、@Onアノテーションを付与すると、引数に指定した時間に実行される。引数はcron書式に準拠する。

day-of-weeka day-of-month については未実装なのでサポートされない。
例えば、@On("0 0 16 * * MON-FRI") のような設定をするとエラーになる。@On("0 0 16 * * ?") ならOK。

@Everyと同じく、”cron.hoge” のように指定すると、application.conf [cron.hoge] の設定を参照する。””空文字のときは定期実行されないので、アプリケーションIDによって動作のON/OFFを分けることができる。

@On("cron.hoge")
public class MyJob extends Job { ...
# %prodのときだけ実行する
cron.hoge=
%prod.cron.hoge=0 0 16 * * ?

おまけ

インスタンスは起動時に一度だけ生成され、アプリケーション実行中はずっと残りつづける。

定期ジョブの実行は、java.util.concurrent.ScheduledThreadPoolExecutorクラスで実現している。
sardineの日記 – scheduleAtFixedRate() の正確さ ここの情報をみると、あまり時刻に正確さを期待してはいけないのかもしれない。

いずれの方法でのジョブ実行もplay.jobs.Job.call()からの呼出となる。
そこでは、before, filter, afterといった処理が適宜呼び出されるようになっている。DBへのトランザクション開始もfilter内で解決されているようだ。

自前でトランザクション管理する際は、ジョブを記述しているクラスに対して@NoTransactionアノテーションを付ける。

@NoTransaction
public class MyJob extends Job { ...

LEAVE A COMMENT