Posted at

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

More than 3 years have passed since last update.


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");