Apexを使った1日に複数回動作させるバッチ処理

セールスフォース

 Salesforceでバッチ処理を作成する方法としてはフロー処理の中の「スケジュールトリガーフロー」を使ってフロー処理として記述することが可能ですが、フローを動作させる頻度が「1回のみ、毎日、毎週」しかなく、1時間ごとに動作させるような設定ができません。

 今回は、10分ごとに処理を行うための実装をApexを使って行います。

1.バッチクラスとスケジュールクラス

 スケジュールの開始はスケジュールクラスを継承したクラスで実施し、この中からバッチクラスを呼び出し、バッチを実行します。

1.1 バッチクラスの作成

 バッチクラスを実装するためにはバッチクラスをインプリメントする必要があります。

 public class xxxxBatch implements Database.Batchable<sObject>,Database.Stateful { ....

 また以下のメソッドを実装する必要があります。

  
/* バッチ処理開始時に最初に呼び出される。バッチ処理対象となるレコードを返却するQueryLocatorを返す。*/ 
public Database.QueryLocator start(Database.BatchableContext bc) {
       処理
       return Database.getQueryLocator(xxxxx);
}
/* バッチサイズで指定されたレコード数の単位で、呼び出される。*/
public void execute(Database.BatchableContext bc,List<sObject> executeRecords) {                   
       処理
}
/* バッチ処理の終了時に呼び出される。終了処理があれば実装する */
public void finish(Database.BatchableContext bc) {
       処理
}

 それぞれのメソッドの記述内容は以下の様になります。

 startメソッドでは、DBの情報を取得するためのQueryを作成しそれを返却します。

public Database.QueryLocator start(Database.BachableContext bc) {
           string query = 'select XXXX from YYYY';           return Database.getQuery(query);
}

 startメソッドの終了後、executeメソッドが呼び出されます。その際startの返却値であるQueryが実行され、その結果がexecuteメソッドの第二引数に渡され、executeメソッドが呼び出されます。
 executeメソッドでは主たる処理を記述します。

public void execute(Database.BatchableContext bc,List(sObject> executeRecords) {
       ......
       for(hoge xx : executeRecords) {
          .........
       }
       .......
}

 executeメソッドに引き渡されたQeryの実行結果を順に取り出して処理を実施します。
 executeメソッドでExceptionが発生した場合、このトランザクションで実行されたものがロールバックされてしまいます。そのため、この処理の中でメール送信などを行っている場合にはメールを送信する処理もトランザクションの一部となるためメールが送信されないことになります。
 そのためtry~catch()を使用してExceptionを捕まえて処理することが必要となります。
 最後にfinishメソッドが実行されます。今回はこのfinishメソッド中で次のスケジュールを設定します。

public void finish(Database.BatchableContext bc) {
       DateTime nextSchedTime = DateTime.now().addMinutes(10);
       xxxxBatchSchedule cls = new xxxxBactchSchedule();
       String nextJobName = 'xxxBatchSchedule_'+nextSchedTime.format('yyyyNNddHHmm');
       String schd = nextSchedTime.format('0 m H d M ? yyyy');
       System.schedule(nextJobName,schd,cls);
}

 スケジュール設定について簡単な説明を以下に記載します。

DateTime nextSchedTime = DateTime.now().addMinutes(10);

 次にバッチを起動する時間を設定しています。10分毎にバッチ処理を実施するため、現在時間にaddMinutes()メソッドをつかって10分を加算し、次にバッチ処理を起動する時間を算出しています。

  xxxxBatchSchedule cls = new xxxxBactchSchedule();

 次節で説明するスケジューラクラスをインスタンス化しています。

  String nextJobName = 'xxxBatchSchedule_'+nextSchedTime.format('yyyyNNddHHmm');
  String schd = nextSchedTime.format('0 m H d M ? yyyy');

System.scheduleメソッドに渡すための、スケジュール名と、スケジュール設定する時間を作成しています。スケジュール名は一意でないといけないので、スケジュール時間を付加しています。

System.schedule(nextJobName,schd,cls);

スケジュール設定を行っています。

1.2 スケジュールクラスの作成

 スケジュールクラスでは、Schedulableをimprementします。またスケジュール済のパスが同時に処理できるレコードの数を指定します。デフォルトおよび最大値は200となっています。

 バッチサイズについては分単位、バッチ処理、および制限の強化によるスケジュール済みパスのパワーアップを参照してください。

public class xxxxBactchSchedule imprements Schedulable{
       private final Intefer BATCH_SIZE = 100;
       public xxxxBatchSchedule() {
 
       }
       public void execute(SchedulableContext sc) {
              xxxxBatch bt = new xxxxBatch();
              Database.executeBatch(bt,BATCH_SIZE);
       }
}

 Schedulableクラスのinprementsではexecuteメソッドを実装する必要があります。このexecuteメソッドはglobalまたはpublicで宣言する必要があります。
 executeメソッドの中でインスタンス化されているのは前節で定義したバッチクラスです。

2.Apexスケジューラの設定

 作成したスケジューラを起動するために、Apexスケジューラを設定します。

(1)Apexをスケジュール

 1.ホームタブをクリックし、検索窓からApexを検索します。
2.検索結果のカスタムコードのApexクラスをクリックします。
 3.「Apexをスケジュール」をクリックする

Apexをスケジュールを選択
図1 Apexをスケジュールを選択

(2)スケジュールを設定

スケジュール設定
図2 スケジュール設定

 1.ジョブ名:スケジュールジョブ名を設定
 2.Apexクラス:上記で作成したスケジュールクラス(xxxxBatchSchedule)を指定
 3.頻度、開始日時、終了日時、希望開始時刻を設定する

 注意事項
 1.頻度は、「毎週」または「毎月」しか選択できません。終了日までは指定した頻度でスケジュールが実行されます。上記のスケジュールクラスで設定した時刻とは異なるタイミングでバッチが起動される場合があります。そのため、スケジュールが重複設定されないように、頻度、終了日の設定を行う必要があります。
 2.ジョブキューの状況によっては、指定した日時時刻でのジョブ起動がされない場合があります。

3.スケジュール済のジョブの確認

 バッチクラス(xxxxBatch)で設定したスケジュールは、「設定」→「スケジュール済みジョブ」で確認することができます。

スケジュール済みジョブを確認する方法
図3. スケジュール済みジョブの確認

 アクションに「Manage」と表示されている場合、これをクリックすると起点となったスケジュールの詳細を見ることができます。

スケジュールの詳細表示
図4. スケジュールの詳細表示

 スケジュールを停止する場合には最新のスケジュールの削除アクションをクリックしてスケジュールを削除する必要があります。あわせて、起点となったスケジュールが定期的に実行されるように設定されているためこれも削除する必要があります。

 SFDCのスケジュールに関してはApex スケジューラを参照してください。