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

Newer Version Available

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

future メソッド

future メソッドは、バッググラウンドで非同期で実行されます。外部 Web サービスへのコールアウト、独自のスレッドを独自の時間に実行する処理など、長時間にわたる処理を実行する場合に future メソッドをコールできます。また、混合 DML エラーを回避するために異なる sObject 型に対する DML 操作を分離する場合にも future メソッドを使用できます。各 future メソッドは、キューに入れられ、システムリソースが使用可能になったときに実行されます。この方法によって、長時間にわたる処理の完了を待たずにコードを実行できます。future メソッドを使用する利点は、SOQL クエリの制限やヒープサイズ制限など、一部のガバナ制限値が高くなる点にあります。

future メソッドを定義するには、単に次のように future アノテーションを使用してアノテーションを付加します。

1swfobject.registerObject("clippy.codeblock-0", "9");
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17global class FutureClass
18{
19    @future
20    public static void myFutureMethod()
21    {   
22         // Perform some operations
23    }
24}

future アノテーションのあるメソッドは静的メソッドである必要があり、void 型のみを返します。指定するパラメータはプリミティブデータ型、プリミティブデータ型の配列、プリミティブデータ型のコレクションである必要があります。future アノテーションのあるメソッドは、sObject またはオブジェクトを引数として取ることはできません。

future メソッドに sObject を引数として渡せない理由は、メソッドをコールしてからそのメソッドを実行するまでの間に sObject が変更されてしまう可能性があるためです。この場合、future メソッドが以前の sObject 値を取得して新しい値を上書きしてしまう可能性があります。  データベースにすでに存在する sObject を使用するには、代わりに sObject ID (または ID のコレクション) を渡し、ID を使用して最新のレコードに対してクエリを実行します。次の例では、ID のリストを使用してこれを実行する方法を示します。

1swfobject.registerObject("clippy.codeblock-1", "9");
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17global class FutureMethodRecordProcessing
18{
19    @future
20    public static void processRecords(List<ID> recordIds)
21    {   
22         // Get those records based on the IDs
23         List<Account> accts = [SELECT Name FROM Account WHERE Id IN :recordIds];
24         // Process records
25    }
26}

次の例は、外部サービスへのコールアウトを実行する future メソッドの骨格です。このアノテーションは、コールアウトが許可されることを示す追加パラメータ (callout=true) を取っています。コールアウトについての詳細は、Apex を使用したコールアウトの呼び出しを参照してください。

1swfobject.registerObject("clippy.codeblock-2", "9");
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17global class FutureMethodExample
18{
19    @future(callout=true)
20    public static void getStockQuotes(String acctName)
21    {   
22         // Perform a callout to an external service
23    }
24
25}

null 以外のロールを持つユーザの挿入は、他の sObject に対する DML 操作とは別のスレッドで実行する必要があります。次の例では、future メソッドを使用してこれを行っています。future メソッド insertUserWithRole は、Util クラスで定義され、COO ロールを持つユーザの挿入を実行します。この future メソッドを使用するには、組織に COO ロールを定義しておく必要があります。MixedDMLFutureuseFutureMethod メソッドで、取引先が挿入され、future メソッド insertUserWithRole がコールされます。

次は、null 以外のロールを持つユーザを挿入する future メソッドが含まれる、Util クラスの定義です。

1swfobject.registerObject("clippy.codeblock-3", "9");
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17public class Util {
18    @future
19    public static void insertUserWithRole(
20        String uname, String al, String em, String lname) {
21
22        Profile p = [SELECT Id FROM Profile WHERE Name='Standard User'];
23        UserRole r = [SELECT Id FROM UserRole WHERE Name='COO'];
24        // Create new user with a non-null user role ID 
25        User u = new User(alias = al, email=em, 
26            emailencodingkey='UTF-8', lastname=lname, 
27            languagelocalekey='en_US', 
28            localesidkey='en_US', profileid = p.Id, userroleid = r.Id,
29            timezonesidkey='America/Los_Angeles', 
30            username=uname);
31        insert u;
32    }
33}

これは、上記で定義した future メソッドをコールするメインメソッドが含まれるクラスです。

1swfobject.registerObject("clippy.codeblock-4", "9");
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17public class MixedDMLFuture {
18    public static void useFutureMethod() {
19        // First DML operation
20        Account a = new Account(Name='Acme');
21        insert a;
22        
23        // This next operation (insert a user with a role) 
24        // can't be mixed with the previous insert unless 
25        // it is within a future method. 
26        // Call future method to insert a user with a role.
27        Util.insertUserWithRole(
28            'mruiz@awcomputing.com', 'mruiz', 
29            'mruiz@awcomputing.com', 'Ruiz');        
30    }
31}

future メソッドを呼び出す方法は、他のメソッドを呼び出す方法と同じです。ただし、future メソッドで別の future メソッドを呼び出すことはできません。

future アノテーションのあるメソッドには次のような制限事項があります。

  • Apex 呼び出しごとの、メソッドのコール数は 50 以下にする必要があります。

    startTest ブロックおよび stopTest ブロックでコールされた @future または executeBatch などの非同期コールは、キュー内ジョブ数の制限に対してカウントされません。

    メモ

  • 24 時間あたりの future メソッドの最大呼び出し数は、250,000 または組織のユーザライセンス数の 200 倍のいずれか大きいほうです。これは組織全体の制限で、他のすべての非同期 Apex (Apex 一括処理、キュー可能 Apex、スケジュール済み Apex、および future メソッド) と共有されます。この制限のカウント対象となるライセンスは、Salesforce フルユーザライセンスまたは Force.com アプリケーションサブスクリプションのユーザライセンスです。Chatter FreeChatter カスタマーユーザ、カスタマーポータルユーザ、およびパートナーポータルユーザライセンスは含まれません。

Salesforce サービスメンテナンスダウンタイム前にキューに入れられた future メソッドジョブは、キューに入れられたままになります。サービスのダウンタイムが終了してシステムリソースが使用可能になったときに、キューにある future メソッドが実行されます。ダウンタイム中に future メソッドが実行されていた場合、その future メソッドの実行はロールバックされ、サービスが再開された後に再実行されます。

メモ

future メソッドのテスト

future アノテーションのあるメソッドをテストするには、startTest()stopTest() コードブロック内でメソッドを含むクラスをコールします。startTest メソッドの後に作成されたすべての非同期コールはシステムによって収集されます。stopTest を実行する場合、すべての非同期プロセスが同期して実行されます。

この例では、テストクラスは次のようになります。
1swfobject.registerObject("clippy.codeblock-5", "9");
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17@isTest
18private class MixedDMLFutureTest {
19    @isTest static void test1() {
20        User thisUser = [SELECT Id FROM User WHERE Id = :UserInfo.getUserId()];
21       // System.runAs() allows mixed DML operations in test context
22        System.runAs(thisUser) {
23            // startTest/stopTest block to run future method synchronously
24            Test.startTest();        
25            MixedDMLFuture.useFutureMethod();
26            Test.stopTest();
27        }
28        // The future method will run after Test.stopTest();
29    
30        // Verify account is inserted
31        Account[] accts = [SELECT Id from Account WHERE Name='Acme'];
32        System.assertEquals(1, accts.size());
33        // Verify user is inserted
34        User[] users = [SELECT Id from User where username='mruiz@awcomputing.com'];
35        System.assertEquals(1, users.size());
36    }
37}

future メソッドのパフォーマンスのベストプラクティス

Salesforce では、キューベースのフレームワークを使用して、future メソッドや Apex 一括処理などのソースからの非同期プロセスを処理します。このキューは、組織間で要求ワークロードを調整するために使用します。組織が非同期プロセスでキューを効率的に使用していることを確認するには、次のベストプラクティスを使用します。

  • 可能な限り、非同期キューに多数の future メソッドを追加することは避けます。キュー内で 1 つの組織の未処理要求が 2,000 を上回ると、その組織からの以降の要求は遅延し、その間に他の組織からの要求が処理されます。
  • future メソッドができるだけ速く実行されるようにします。一括処理ジョブの高速実行を実現するには、Web サービスのコールアウト時間を最小化し、future メソッドで使用されるクエリを調整します。キュー内に多数の要求がある場合、future メソッドの実行時間が長くなるにつれ、キューにある他の要求が遅延する可能性が高くなります。
  • future メソッドをより大規模にテストします。可能な場合は、予想される最大数の future メソッドを生成する環境を使用してテストします。これは遅延が発生するかどうかの判断に役立ちます。
  • 多数のレコードの処理には、future メソッドの代わりに Apex 一括処理の使用を検討します。