Queueable Apex とは
future
メソッドと同様に非同期処理のジョブを送信でき、加えて下記の利点がある
- Queueable クラスには、sObject 型やカスタム Apex 型など、プリミティブ以外のデータ型のメンバー変数を含めることができる
System.enqueueJob
メソッドを呼び出してジョブを送信すると、メソッドが AsyncApexJob
レコードの ID を返す。
- この ID を使用して、Salesforce ユーザーインターフェースの [Apex ジョブ] ページから、またはプログラムで
AsyncApexJob
のレコードを照会する方法で、ジョブを識別してその進行状況を監視できる.
- 実行中のジョブから 2 つ目のジョブを開始することで、2 つのジョブを連鎖的に実行することができる
queueable と future の比較
- ほとんどの場合
future
を使用せずにqueueable
にreplaceできる
future
メソッドを使用する場合は、機能が同期実行されることもあれば、非同期実行されることもある場合
Queueable Apexの構文
public class SomeClass implements Queueable {
public void execute(QueueableContext context) {
}
}
public class UpdateParentAccount implements Queueable {
private List<Account> accounts;
private ID parent;
public UpdateParentAccount(List<Account> records, ID id) {
this.accounts = records;
this.parent = id;
}
public void execute(QueueableContext context) {
for (Account account : accounts) {
account.parentId = parent;
}
update accounts;
}
}
List<Account> accounts = [select id from account where billingstate = ‘NY’];
Id parentId = [select id from account where name = 'ACME Corp'][0].Id;
UpdateParentAccount updateJob = new UpdateParentAccount(accounts, parentId);
ID jobID = System.enqueueJob(updateJob);
- ジョブがキューに追加され、システムリソースが使用可能になると処理されるので、取得した
jobID
を使用して[Apex Job (Apex ジョブ)] ページから、またはプログラムで AsyncApexJob
を照会する方法で、進行状況を監視できる
SELECT Id, Status, NumberOfErrors FROM AsyncApexJob WHERE Id = :jobID
Queueable Apex のテスト
@isTest
public class UpdateParentAccountTest {
@testSetup
static void setup() {
List<Account> accounts = new List<Account>();
accounts.add(new Account(name='Parent'));
for (Integer i = 0; i < 100; i++) {
accounts.add(new Account(
name='Test Account'+i
));
}
insert accounts;
}
static testmethod void testQueueable() {
Id parentId = [select id from account where name = 'Parent'][0].Id;
List<Account> accounts = [select id, name from account where name like 'Test Account%'];
UpdateParentAccount updater = new UpdateParentAccount(accounts, parentId);
Test.startTest();
System.enqueueJob(updater);
Test.stopTest();
System.assertEquals(100, [select count() from account where parentId = :parentId]);
}
}
ジョブのチューニング
- ジョブを連続して実行する場合は、
execute()
メソッドから2つ目のジョブを送信する
- 1ジョブにつきチューニングできるのは1子ジョブのみ
- しかし階層については制限はないので、子ジョブからさらに子ジョブを呼び出すようにすれば良い。
- 1ジョブから複数の子ジョブを呼び出すことはできない。
public class FirstJob implements Queueable {
public void execute(QueueableContext context) {
System.enqueueJob(new SecondJob());
}
}