tyoshikawa1106のブログ

- Force.com Developer Blog -

SFDC:Apexバッチの数分おきに繰り返し実行を試してみました

Apexバッチを指定の時間や定期的に実行したい場合は、スケジュールバッチの仕組みを使って対応します。スケジュールバッチは「implements Schedulable 」を宣言したクラスを用意することで作成できます。

Scheduleクラス

f:id:tyoshikawa1106:20190916082622p:plain

Connectクラス

f:id:tyoshikawa1106:20190916082421p:plain


上記のようなクラスを用意するとApexクラスの設定で「Apex をスケジュール」の仕組みが利用できるようになります。
f:id:tyoshikawa1106:20190916082810p:plain


こちらがApexスケジュールの設定画面です。
f:id:tyoshikawa1106:20190916082918p:plain


開始日と終了日を設定でき、実行対象の曜日と時間を指定できます。一日一回のスケジュール実行という要件の場合はこちらの設定画面のみで対応できます。注意が必要なのは数分単位で実行したい場合です。Apex をスケジュールの設定では1時間単位でのみ実行時間を指定できます。そのため5分間隔や15分間隔での実行はサポートされていません。今回は設定ページのみでは実現できない数分間隔での実行方法を紹介します。


Apexバッチの処理は「コンストラクタ」「start」「execute」「finish」のメソッドで構成されます。「start」のメソッドで対象となるデータを取得します。「execute」のメソッドでメインの処理が実行されます。バッチサイズの件数分に分割して繰り返し処理を実行します。(バッチサイズ200件で1000件対象データがある場合は200×5回繰り返し実行されます。)「finish」のメソッドが最後に一回呼び出されて処理を実行します。

Apexバッチクラス

f:id:tyoshikawa1106:20190916083634p:plain


最後に実行される「finish」メソッドで次のスケジュールバッチを登録することが可能です。
f:id:tyoshikawa1106:20190916084102p:plain


スケジュールバッチは「System.schedule(jobName, sch, cls);」の処理で登録できます。ジョブ名、スケジュール実行時間、対象のスケジュールバッチクラスが引数として必要です。

/**
 * Finish
 */
public void finish(Database.BatchableContext BC) {
    // 次回スケジュールバッチ登録判定
    if (this.isNextBatch) {
        // 次回スケジュールバッチ実行時間取得
        Datetime nextBatchTime = Datetime.now().addMinutes(5);
        // 次回スケジュールバッチ実行時間登録
        OpportunityChatterPostBatchSchedule cls = new OpportunityChatterPostBatchSchedule();
        String jobName = 'OpportunityChatterPostBatchScheduleJob_' + nextBatchTime.format('yyyyMMddHHmm');
        String sch = nextBatchTime.format('0 m H d M ? yyyy');
        System.schedule(jobName, sch, cls);
    }
}

ジョブ名はユニークにする必要があります。Apex処理で自動登録する場合は実行日時などを追加するのが良さそうです。
スケジュール実行時間は文字列で宣言します。引数の渡し方はいくつか用意されていますが任意の時間に一回実行したい場合は下記の引数を渡します。

(秒 分 時 日 月 ? 年)

時間は24時間表記です。DateTime型の.formatでは「hh:mm:ss」と宣言できますが「hh」を「HH」と大文字で宣言することで24時間表記になります。また「H」とのみ宣言することで0埋めがされなくなります。


この方法で実行した結果がこちらです。約5分おきに実行されています。
f:id:tyoshikawa1106:20190916084729p:plain


検証時ですが20:00など切りの良い時間から開始しましたが一晩立つ頃には1分ズレが発生しました。こればバッチ実行は宣言してすぐに実行されない(一度キューに貯まる)ことと、Finsh時点での日時を基準に5分後で登録したので処理に時間がかかることで1分間のズレが発生したためと思います。


5分おきに実行する場合はこうしたズレも考慮した方が良いみたいです。またバッチのキューは一度に登録できる件数に上限があります。夜間バッチなど処理が多く実行される場合は登録をスキップするなどの考慮も必要になると思います。

補足

上記サンプルのバッチクラスでは下記の「Helper」クラスと「Dao」クラスを宣言しています。目的に合わせてクラスを分けるとメンテがしやすいと思います。

Helperクラス

f:id:tyoshikawa1106:20190916085723p:plain

Daoクラス

f:id:tyoshikawa1106:20190916085745p:plain

利用例

今回の数分単位でのバッチ実行ですが、例として新規商談を登録した際にChatterに投稿すると行った場面で利用できます。社内ユーザが新規商談を登録した際には何も気にせずプロセスビルダーでそのまま対応できますが、Force.comサイトで作成したフォーム経由で登録された場合など社外ユーザの作成時には通常Chatter投稿ができません。Apexのスケジュールバッチの場合は管理者権限で実行できるので、社外ユーザ権限で商談作成できる仕組みを構築したいときなどに利用できると思います。

関連・参考