を-1ページで.png)
Queueableって、便利なんですが「なんとなく」で触ると地味に事故ります。
自分も最初は、テストは通るのに本番で順番がズレたり、制限に当たって詰まったりしました。
ってことで結論です。
結論:Queueableは『enqueueJobでキューに積まれる非同期処理』。
実行順と制限を押さえて、設計をシンプルにすると安定します。
Contents
Queueableとは?
Queueableは、Apexの非同期処理の1つです。
同期処理(通常のApex)とは違い、実行は「今すぐ」ではなく『キューに積まれて後で実行』されます。
よく使う理由はこのへんです。
- 画面やトリガの処理を軽くできる(ユーザの待ち時間が減る)
- 処理を分割して段階的に進められる
- バッチほど大げさにせず、非同期化できる
enqueueJobの最小形(まずはこれだけ)
Queueableの基本形はこうです。
Queueableクラス(最小)
public class SampleQueueable implements Queueable {
public void execute(QueueableContext context) {
// ここに非同期でやりたい処理を書く
System.debug('Queueable executed');
}
}
呼び出し側(enqueueJob)
System.enqueueJob(new SampleQueueable());
これで『キューに積まれる』までが確定します。
実行順はどう決まる?
ここが一番の落とし穴になりやすいです。
結論から言うと、Queueableは『キューに積まれた順で実行される』と考えるのが基本ですが、現実はもう少し注意が必要です。
まず押さえる前提
- enqueueJobした瞬間に実行されるわけではない
- 実行タイミングはSalesforce側(プラットフォーム側)が管理する
- だから「この順で必ず動く」を前提に設計すると痛い
じゃあどう設計する?
順番が大事な処理は、次のどれかに寄せるのが堅いです。
- 1つのQueueableで完結させる(分割しない)
- 分割するなら『チェーン(連鎖)』して順番を固定する
- そもそも順番に依存しない設計に寄せる(理想)
チェーン(連鎖)で順番を固定する
Queueableは、executeの中で次のQueueableをenqueueできます。
これで「次にこれ」を作れます。
public class Step1Queueable implements Queueable {
public void execute(QueueableContext context) {
// Step1の処理
// ...
// 次の処理へ
System.enqueueJob(new Step2Queueable());
}
}
public class Step2Queueable implements Queueable {
public void execute(QueueableContext context) {
// Step2の処理
// ...
}
}
注意:チェーンは強いですが、やりすぎると制限に当たります(後述)。
よく踏む制限(最低限これだけ)
Queueableは「無限に投げられる」わけではないです。
制限は細かくありますが、現場で踏みやすいのはこの3つです。
1) 1回のトランザクションでenqueueできる数に上限がある
トリガやフロー、Apex処理の中でループしながらenqueueすると、すぐ危険です。
ダメな例(雰囲気)
for(Account a : accounts){
System.enqueueJob(new SampleQueueable()); // これを大量にやると危険
}
対策:enqueueは『1回』に寄せて、Queueableの中でまとめて処理する。
2) チェーン(連鎖)にも上限がある
「Step1 → Step2 → Step3 → …」を無限に繋ぐ設計は危険です。
対策:
- 連鎖は最小限(本当に順番が必要な部分だけ)
- 大量処理ならBatchを検討
- 途中状態はレコード(ステータス)で管理して、再実行可能にしておく
3) 同時実行・再実行で二重更新が起きやすい
Queueableは「後で動く」ので、同じ対象に対して別のQueueableが走ると衝突します。
結果として、上書きやロック、想定外の更新が起きます。
対策:
- 対象レコードに『処理中フラグ』や『バージョン番号』を置いてガードする
- そもそも同じ対象を並列で触らない設計に寄せる
- 失敗しても再実行できる形にする(1回で完璧を狙わない)
どうテストする?(最小だけ)
Queueableは、テストで『startTest/stopTest』で挟むのが基本です。
@IsTest(SeeAllData=false)
public class SampleQueueableTest {
@IsTest
static void testQueueable() {
Test.startTest();
System.enqueueJob(new SampleQueueable());
Test.stopTest();
// stopTest後に検証を書く
System.assertEquals(true, true);
}
}
「検証ができない」で詰まる場合は、Queueableが更新する対象(項目)を用意して、stopTest後にSELECTして確認するのが堅いです。
まとめ
- Queueableは『enqueueJobでキューに積まれる非同期処理』
- 実行順は「保証される」と思い込みすぎない(順番が必要ならチェーンで固定)
- 制限は踏みやすい(enqueue乱発、チェーン過多、二重更新)
- テストは『startTest/stopTestで挟んで、stopTest後に検証』

