AppEngine の便利 JobQueue クラス DeferredTask の使い方

  • 2
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

DeferredTask とは

TaskQueue を、URL ハンドラの実装なしに使える便利クラスです。

通常、TaskQueue は指定された URL を叩いて Task を実行します。
この挙動は厳密な設計には便利ですが、Task の種類の数だけ URL を制御しなければなりません。
新たにルーティングを設定し、新たにコントローラメソッドを実装する必要があります。

これらを廃し、より気楽に使えるようにしたのが DeferredTask クラスです。
必要な要素はたった一つ、DeferredTask interface (#run のみ) を実装したクラスのみです。

基本的な使い方

public class SomeTask implements DeferredTask {
    @Override
    public void run() {
        Log.d("SomeTask", "Hello World!");
    }
}

// 登録
final TaskOptions option = TaskOptions.Builder.withPayload(new SomeTask());
QueueFactory.getDefaultQueue().add(option);

パラメータの渡し方

プロパティ持たせて渡します。

public class SomeTask implements DeferredTask {
    private static final Logger logger = Logger.getLogger(SomeTask.class.getSimpleName());

    private final String someParam;

    public SomeTask(String someParam) {
        this.someParam = someParam;
    }

    @Override
    public void run() {
        logger.info("Performing a task with someParam: " + someParam);
    }
}

TaskQueue への登録

インスタンス化し Payload として TaskQueue に登録すれば勝手に処理されます。

final TaskOptions option = TaskOptions.Builder
    .withPayload(new SomeTask("someparamvalue"));
QueueFactory.getDefaultQueue().add(option);

内部的には POST /_ah/queue/__deferred__ でこのタスクをハンドリングしてくれる。
タスクに渡したパラメータはログや TaskQueue の管理画面に出ないので注意。

Task 内でパラメータを Log しておくことをおすすめします。

注意点

DeferredTask は Serializable であることに気を付けてください。内部的には、DeferredTask はシリアライズされて TaskQueue に突っ込まれ、内部的にデシリアライズされて run() されています。

そのため、内部クラスで実装すると、Serializable でないと思われる親クラスへの参照を持ってしまうため、正常に動きません。(多分)
同様の理由で、匿名クラスでの実装も出来ません。文法的には一番便利なのですが…

上記の理由により、親クラスの内部プロパティや、今のメソッドスコープの変数に依存した実装は出来ません。
要は、必要な情報は全て DeferredTask インスタンスに渡してあげてください。

便利な分、シリアライズの面で取り扱いが難しくなっています。この点を注意し、DeferredTask は気軽なタスクで利用しましょう。

TaskQueue について便利情報

○ 秒後とかしたければ countdownMillis(long) を使う。

final TaskOptions option = TaskOptions.Builder
    .withPayload(new SomeTask("someparamvalue"))
    .countdownMillis(10000); // 10 秒後

taskName(String) を使えば TaskQueue 管理画面に名前が出ます(多分)

final TaskOptions option = TaskOptions.Builder
    .withPayload(new SomeTask("someparamvalue"))
    .taskName("SomeTask");