Salesforce APEX トリガーコールアウトチェーン [日本語]

Salesforce APEX トリガーコールアウトチェーン [日本語]

2020, Sep 11    

最近、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 のコールアウトのためのチェイニングは完了です。