Salesforce APEX トリガーコールアウトチェーン [日本語]
最近、Salesforce の制限で課題に直面しました。通常は不可能な Apex トリガーからのチェーンコールアウトを行う必要がありました。APEX トリガーからのコールアウトはすべて制限されており、トランザクションごとに 10 回までの呼び出しに制限されている @future メソッド呼び出しでしかできません。
この場合、既に外部 API への@future コールアウトを行っているトリガーがあり、このコールから返されたデータを使用して別の API コールアウトを行う必要がありました。また、同じオブジェクトトリガー、例えば Account や Contact を使っても、@future メソッドから開始される継続的なアップデートは、この非同期@future コンテキストの制限によって制約されてしまいます。
私ができたのは、この問題を回避するためにQueueable Apex
この問題はQueueable Apexを使うことで、回避できます。これは、トリガーが@future メソッドで API コールアウトを実行している間、API コールは非同期(サーバー側では別スレッド)で実行され、その@future メソッド内の全ての DML 操作は単一トランザクションの制限に制約されてしまいます。しかし、ここでQueueable Apex(キューアブルアペックス)を使うと、@future コンテキストとは別の作業をするために、新しい非同期プロセスを起動して、その制限を回避することが可能となります。
実際には、Salesforce はこの作業を、リソースが利用可能になるとスケジュール通りに実行されるバッチジョブのようなキューに置いています。この作業を完了させるためのトリガー @future メソッドから非同期のバッチジョブを起動するようなものです。
これは、Queueable APEX クラスの実装です。
public class SampleServiceQueue implements Queueable, Database.AllowsCallouts {
public final List<Id> idList;
public SampleServiceQueue(List<Id> idList){
this.idList = idList;
}
public void execute(QueueableContext context) {
// This method will make a REST API call
SampleService.accountPaymentService(idList);
}
}
このジョブは、監視可能なジョブ ID を返す System メソッドの呼び出しによって開始されます。
List<Account> acctList = Trigger.new; // Get this from a trigger call
// Assemble List of IDs for queueable method
List<Id> acctIdList = new List<Id>();
for (Account a : acctList){
acctIdList.add(a.Id);
}
if (acctIdList != null && acctIdList.size()>0){
Id jobID = System.enqueueJob(new SampleServiceQueue(acctIdList));
}
これは、新しい Queueable Class (キューアブルクラス)のメソッドをカバーするためのユニットテストです。
@isTest
private class SampleServiceQueueTest {
static testMethod void SampleQueueTest(){
List<Id> idList = new List<Id>();
SamlpleServiceQueue mq = new SampleServiceQueue(idList);
}
}
このテストメソッドは、デプロイのために 100%のテストカバレッジを得る必要があります。 これで APEX Trigger のコールアウトのためのチェイニングは完了です。