この文章は Salesforce 機械翻訳システムを使用して翻訳されました。詳細はこちらをご参照ください。
英語に切り替える

Newer Version Available

This content describes an older version of this product. View Latest

キュー可能 Apex

非同期 Apex プロセスを制御するには、Queueable インターフェースを使用します。このインターフェースにより、ジョブをキューに追加して監視できます。このインターフェースを使用することで、future メソッドを使用する場合に比べ、非同期 Apex コードの実行が機能強化されます。

大規模なデータベース操作や外部 Web サービスのコールアウトなど実行に長時間かかる Apex プロセスは、Queueable インターフェースを実装し、ジョブを Apex ジョブキューに追加することで非同期に実行できます。この場合、非同期 Apex ジョブは、それ自身のスレッドのバックグラウンドで実行され、メインの Apex ロジックの実行を遅延させることはありません。キュー内にある各ジョブは、システムリソースが使用可能になると実行されます。Queueable インターフェースメソッドを使用するメリットは、ヒープサイズ制限など一部のガバナ制限値が、同期 Apex の場合よりも緩和される点にあります。

トランザクションによってキューに追加された実行予定のキュー可能ジョブは、Apex トランザクションがロールバックされた場合、処理されません。

メモ

キュー可能ジョブと future メソッドはどちらもキューに入れられてから実行されるという点で似ていますが、キュー可能ジョブには次のようなメリットもあります。

  • ジョブ ID の取得: System.enqueueJob メソッドを呼び出してジョブを送信すると、メソッドは新しいジョブの ID を返します。この ID は AsyncApexJob レコードの ID に対応します。この ID を使用してジョブの識別と監視を行うには、Salesforce UI ([Apex ジョブ] ページ) を使用する方法と、プログラムで AsyncApexJob のレコードを照会する方法があります。
  • 非プリミティブ型の使用: キュー可能クラスには、sObject 型やカスタム Apex 型など、非プリミティブデータ型のメンバー変数を含めることができます。これらのオブジェクトには、ジョブの実行時にアクセスできます。
  • ジョブのチェーニング: 実行中のジョブから 2 つ目のジョブを開始することで、2 つのジョブを連鎖的に実行することができます。ジョブのチェーニングは、別の先に実行するプロセスに依存するプロセスがある場合に便利です。

チェーニングされたキュー可能ジョブの最大スタック深度を設定することができます。これにより、Developer Edition 組織と Trial Edition 組織のデフォルト制限である 5 が上書きされます。

transient として宣言された変数は、シリアライゼーションとデシリアライゼーションで無視され、その値はキュー可能 Apex では null に設定されます。

メモ

非同期実行キューへのキュー可能ジョブの追加

次の例では、Queueable インターフェースが実装されます。この例の execute メソッドは、新規取引先を挿入します。ジョブをキューに追加するには、System.enqueueJob(queueable) メソッドが使用されます。
1public class AsyncExecutionExample implements Queueable {
2    public void execute(QueueableContext context) {
3        Account a = new Account(Name='Acme',Phone='(415) 555-1212');
4        insert a;        
5    }
6}
このクラスをジョブとしてキューに追加するには、次のメソッドをコールします。
1ID jobID = System.enqueueJob(new AsyncExecutionExample());

キュー可能クラスを実行のために送信すると、ジョブはキューに追加され、システムリソースが使用可能になると処理されます。ジョブの状況を監視するには、プログラムで AsyncApexJob を照会するか、ユーザーインターフェースの [設定] から、[クイック検索] ボックスに「Apex ジョブ」と入力して [Apex ジョブ] を選択します。

送信したジョブに関する情報を照会するには、System.enqueueJob メソッドが返したジョブ ID で絞り込んで AsyncApexJob に対する SOQL クエリを実行します。次の例では、前の例で取得された jobID 変数を使用します。

1AsyncApexJob jobInfo = [SELECT Status,NumberOfErrors FROM AsyncApexJob WHERE Id=:jobID];

future ジョブと同様、キュー可能ジョブはバッチを処理しません。そのため、処理されたバッチ数と合計バッチ数は常に 0 です。

最小遅延を指定したキュー可能ジョブの追加

最小遅延 (0 ~ 10 分) を指定してキュー可能ジョブを非同期実行キューに追加するには、System.enqueueJob(queueable, delay) メソッドを使用します。遅延は、Apex のテスト中は無視されます。

『Apex リファレンスガイド』System.enqueueJob(queueable, delay)を参照してください。

遅延を 0 に設定すると、キュー可能ジョブができるだけ早く実行されます。チェーニングされたキュー可能ジョブでは、必要に応じてジョブを遅延または停止するメカニズムを実装します。そのようなフェールセーフメカニズムが実装されていないと、日次非同期 Apex 制限にすぐに到達する可能性があります。

警告

キュー可能ジョブの実行前にタイミングを調整した方がよいケースを次に示します。

  • 外部システムがレート制限されていて、迅速なコールアウトを実行するチェーニングされたキュー可能ジョブでオーバーロードできない場合。
  • 結果をポーリングするときに実行が速すぎて日次非同期 Apex 制限を浪費する可能性がある場合。

この例では、実行に使用する Queueable インターフェースのクラス実装のインスタンスを渡して遅延非同期実行のジョブを追加します。ジョブが実行されるまでの最小遅延は 5 分です。

1Integer delayInMinutes = 5;
2ID jobID = System.enqueueJob(new MyQueueableClass(), delayInMinutes);

システム管理者は、遅延パラメーターなしでスケジュールされたキュー可能ジョブのスケジュールで、組織のデフォルトの遅延 (1 ~ 600 秒) を定義できます。デフォルトのキュー可能ジョブの実行を遅らせるメカニズムとして遅延設定を使用します。この設定を省略すると、遅延が追加されていない標準のキュー可能タイミングが Apex で使用されます。

System.enqueueJob(queueable, delay) メソッドを使用すると、組織全体のキューへの追加の遅延設定が無視されます。

メモ

組織全体の遅延は、次のいずれかの方法で定義します。

  • [設定] の [クイック検索] ボックスに「Apex 設定」と入力し、[遅延パラメーターのないキュー可能ジョブのキューへの追加のデフォルトの最小遅延 (秒)] に値 (1 ~ 600 秒) を入力します。
  • メタデータ API を使用してこの機能をプログラムで有効化するには、『メタデータ API 開発者ガイド』の「ApexSettings」を参照してください。

スタック深度を指定したキュー可能ジョブの追加

最大スタック深度と最小キュー遅延を asyncOptions パラメーターで指定できる System.enqueueJob(queueable, asyncOptions) を使用します。

System.AsyncInfo クラスのプロパティには、現在のスタック深度、最大スタック深度、および最小のキュー可能遅延が含まれています。

System.AsyncInfo クラスのメソッドを使用すると、キュー可能要求で最大スタック深度が設定されているかどうかを判断し、現在実行中のキュー可能ジョブのスタック深度とキュー遅延を取得できます。現在のキュー可能実行に関する情報を使用して、後続のコールで遅延の調整に関する決定を行います。

これらのメソッドは、System.AsyncInfo クラスに含まれます。

  • hasMaxStackDepth()
  • getCurrentQueueableStackDepth()
  • getMaximumQueueableStackDepth()
  • getMinimumQueueableDelayInMinutes()

この例では、スタック深度を使用してチェーニングされたジョブを終了し、非同期 Apex メソッドの 1 日の最大実行数に達しないようにしています。

1// Fibonacci
2public class FibonacciDepthQueueable implements Queueable {
3   
4    private long nMinus1, nMinus2;
5       
6    public static void calculateFibonacciTo(integer depth) {
7        AsyncOptions asyncOptions = new AsyncOptions();
8        asyncOptions.MaximumQueueableStackDepth = depth;
9        System.enqueueJob(new FibonacciDepthQueueable(null, null), asyncOptions);
10    }
11       
12    private FibonacciDepthQueueable(long nMinus1param, long nMinus2param) {
13        nMinus1 = nMinus1param;
14        nMinus2 = nMinus2param;
15    }
16   
17    public void execute(QueueableContext context) {
18       
19        integer depth = AsyncInfo.getCurrentQueueableStackDepth();
20       
21        // Calculate step
22        long fibonacciSequenceStep;
23        switch on (depth) {
24            when 1, 2 {
25                fibonacciSequenceStep = 1;
26            }
27            when else {
28                fibonacciSequenceStep = nMinus1 + nMinus2;
29            }
30        }
31       
32        System.debug('depth: ' + depth + ' fibonacciSequenceStep: ' + fibonacciSequenceStep);
33       
34        if(System.AsyncInfo.hasMaxStackDepth() &&
35           AsyncInfo.getCurrentQueueableStackDepth() >= 
36           AsyncInfo.getMaximumQueueableStackDepth()) {
37            // Reached maximum stack depth
38            Fibonacci__c result = new Fibonacci__c(
39                Depth__c = depth,
40                Result = fibonacciSequenceStep
41                );
42            insert result;
43        } else {
44            System.enqueueJob(new FibonacciDepthQueueable(fibonacciSequenceStep, nMinus1));
45        }
46    }
47}

キュー可能ジョブのテスト

次の例では、テストメソッドでキュー可能ジョブの実行する方法を示します。キュー可能ジョブは、非同期プロセスです。このプロセスがテストメソッド内で実行されるようにするには、ジョブを Test.startTestTest.stopTest 間のブロック内でキューに送信する必要があります。システムは、テストメソッドで開始されたすべての非同期プロセスを、Test.stopTest ステートメントの後に同期して実行します。次に、テストメソッドは、ジョブで作成された取引先を照会して、キュー可能ジョブの結果を検証します。
1@isTest
2public class AsyncExecutionExampleTest {
3    @isTest
4    static void test1() {
5        // startTest/stopTest block to force async processes 
6        //   to run in the test.
7        Test.startTest();        
8        System.enqueueJob(new AsyncExecutionExample());
9        Test.stopTest();
10        
11        // Validate that the job has run
12        // by verifying that the record was created.
13        // This query returns only the account created in test context by the 
14        // Queueable class method.
15        Account acct = [SELECT Name,Phone FROM Account WHERE Name='Acme' LIMIT 1];
16        System.assertNotEquals(null, acct);
17        System.assertEquals('(415) 555-1212', acct.Phone);
18    }
19}

ジョブのチェーニング

最初に別のジョブで他の処理を実行した後にジョブを実行する場合、キュー可能ジョブをチェーニングできます。ジョブを別のジョブにチェーニングするには、キュー可能クラスの execute() メソッドから 2 つ目のジョブを送信します。実行中のジョブから追加できるジョブは 1 つのみです。つまり、親ジョブごとに 1 つの子ジョブしか存在できません。たとえば、2 つ目のクラスが Queueable インターフェースを実装する SecondJob という名前である場合、このクラスを execute() メソッドのキューに次のように追加できます。

1public class AsyncExecutionExample implements Queueable {
2    public void execute(QueueableContext context) {
3        // Your processing logic here       
4
5        // Chain this job to next job by submitting the next job
6        System.enqueueJob(new SecondJob());
7    }
8}

Apex では、キュー可能ジョブが Database.AllowsCallouts マーカーインターフェースを実装している場合、キュー可能ジョブから HTTP コールアウトおよび Web サービスコールアウトを実行できます。このインターフェースを実装するキュー可能ジョブでは、チェーニングされたキュー可能ジョブでもコールアウトを実行できます。

メモ

適切なスタック深度を使用して、チェーニングされたキュー可能ジョブをテストできますが、適用される Apex ガバナ制限に注意してください。「スタック深度を指定したキュー可能ジョブの追加」を参照してください。

キュー可能 Apex の制限

  • キュー内のジョブの実行は、非同期 Apex メソッド実行の共有制限値に対して 1 回加算されます。「Lightning プラットフォームの Apex 制限」を参照してください。
  • 1 つのトランザクションで System.enqueueJob を使用してキューに追加できるのは、最大 50 ジョブです。非同期トランザクション (Apex ジョブの一括処理) では、System.enqueueJob を使用してキューに追加できるジョブは 1 つのみです。あるトランザクションで追加された実行予定ジョブの数を確認するには、Limits.getQueueableJobs() をコールします。
  • チェーニングされたジョブの深度に制限はないため、1 つのジョブから別のジョブにチェーニングできます。このプロセスを新しい子ジョブごとに繰り返して新しい子ジョブにリンクできます。Developer Edition 組織およびトライアル組織の場合、チェーニングされたジョブの最大スタック深度は 5 です。つまり、ジョブのチェーニングは 4 回行うことができます。チェーン内のジョブ数は最初の親キュー可能ジョブを含め最大 5 個です。
  • System.enqueueJob でジョブをチェーニングするとき、既存のジョブから追加できるジョブは 1 つのみです。存在可能な子ジョブは、親のキュー可能ジョブごとに 1 つのみです。同じキュー可能ジョブからの複数の子ジョブの開始は、サポートされていません。