[Salesforce]Apex非同期処理:Futureメソッドの活用
今回は、Salesforce開発で頻繁に利用される「非同期処理」と「@future メソッド」について、実践的な内容を掘り下げて解説します。
以前、こちらの記事で同様の内容を記載していたのですが、だいぶわかりづらかったためアップデートするために改めて取り上げました。さらに、Queueable Apex との違いを詳しく解説し、どちらを使うべきかの判断材料を提供します。
非同期処理の重要性と現場でのユースケース
Salesforce開発では、同期的に処理を行うとガバナ制限(SOQLクエリ制限、DML操作の制限など)に引っかかることがよくあります。特に大量データを操作する場合や、時間のかかる複雑な処理を行う場合は、この問題が顕著になります。
例えば:
• 大量のレコード更新が必要:数万件のレコードを一度に更新する際、同期処理ではガバナ制限に達してしまう。
• 外部システムとの連携:APIを使った外部システムとのデータ連携処理は、時間がかかるため非同期的に行いたい。
• 大量のレポート生成:夜間に大量のレポートを一斉に生成する必要があるが、業務時間中には負荷をかけたくない。
こうしたシナリオでは、非同期処理が強力なツールとなります。特に、ガバナ制限を回避しながら安全に大量データを扱うためには、@future や Queueable Apex の活用が不可欠です。
Futureメソッドの使い方とルール
まずは、Salesforceで最も基本的な非同期処理の手法である**@future メソッド**について見ていきましょう。
基本的な書き方
global class FutureClass {
@future
public static void myFutureMethod() {
// 非同期処理のロジック
}
}
覚えておくべきルール
• メソッドは static でなければならず、戻り値は void のみ。
• 1日に実行できる future メソッドの最大数は、250,000回またはユーザライセンス数の200倍。
• future メソッドの実行順序は保証されない。
• sObject を直接引数に取ることはできない(プリミティブ型やその配列・コレクションのみ)。
実践シナリオ:sObjectを扱う場合
問題の発生例
@future メソッドでは sObject を引数として渡すことができません。
例えば、以下のコードはエラーになります:
@future
public static void createTask(List<Opportunity> newOpps) {
// エラーが発生する
}
これは、非同期処理がキューに入って実行されるまでの間に sObject のデータが変更される可能性があるためです。
解決策:Id を使用
この問題を解決するには、sObject の代わりにレコードの Id を渡して、そのIdを使ってデータを再取得する方法が効果的です。
@future
public static void createTask(Set<Id> oppIds) {
List<Task> tasks = [SELECT Id FROM Task WHERE WhatId IN :oppIds];
// タスク処理を実行
}
これにより、レコードをIdで特定し、非同期処理中でも安全にデータ操作が可能になります。
トリガーで非同期処理を使う
トリガーから非同期処理を呼び出したい場合、Trigger.new のようなコンテキスト変数を直接渡すことはできません。しかし、以下のようにIdセットを使うことで非同期処理を呼び出せます。
public static void setIdAndCallFuture(List<Opportunity> opps) {
Set<Id> oppIds = new Set<Id>();
for (Opportunity opp : opps) {
oppIds.add(opp.Id);
}
createTask(oppIds);
}
このように、トリガー内で Id セットを作成し、それを @future メソッドに渡すことで、非同期処理を安全に実行できます。
@futureとQueueable Apexの違い
次に、@future と Queueable Apex の違いを見てみましょう。どちらも非同期処理を行うための手段ですが、Queueable Apexはより柔軟で拡張性の高いオプションです。
1. 引数の制約
• @future:プリミティブ型、プリミティブ型の配列、コレクションのみ使用可能。sObject を直接渡せません。
• Queueable Apex:sObject を含むオブジェクトを引数に取ることが可能です。これにより、データ操作の柔軟性が大幅に向上します。
2. チェイニングの可否
• @future:他の future メソッドを呼び出すことはできません(チェイニング不可)。
• Queueable Apex:System.enqueueJob を使うことで、ジョブを連鎖的に実行する(チェイニング)ことが可能です。複数の非同期処理を連続的に実行する場合に非常に便利です。
3. 可視性とデバッグ
• @future:ジョブIDなどの取得ができないため、ジョブの状態を簡単に追跡したりデバッグするのが難しいです。
• Queueable Apex:Job ID が取得可能で、System.enqueueJob で返されたIDを使ってジョブの状態を監視し、デバッグがしやすくなります。
4. ガバナ制限
• @future:1つのトランザクション内で呼び出せる future メソッドの数には制限があります(50件まで)。
• Queueable Apex:同じく1トランザクション内で50件までのジョブを呼び出せますが、@future よりも柔軟性があり、特にチェイニングを利用した複雑なシナリオで有利です。
非同期処理のベストプラクティスとデバッグのヒント
1. 非同期処理は適切にスケジュールする
非同期処理はリアルタイム性が不要な場面で活用しましょう。システムの負荷が少ない時間にスケジュールすることで、パフォーマンスを最大限に引き出せます。
2. Queueable Apexの利用を検討する
より複雑なシナリオや、引数に sObject を使う必要がある場合は、Queueable Apex が有効です。エラーハンドリングやデバッグがしやすい点も魅力です。
3. 非同期処理のデバッグ
非同期処理のデバッグはやや難しいため、Queueable Apex を使用してジョブIDを追跡し、ジョブの状態を確認できるようにしましょう。また、ジョブの実行ログを確認することで、エラーの特定と改善が容易になります。
4. 例外処理とリトライ戦略を考える
非同期処理中に失敗が発生した場合、リトライ戦略やエラーログの出力を考慮しましょう。これにより、システムの信頼性を向上させることができます。
まとめ
非同期処理は、Salesforce開発においてガバナ制限を回避しつつ、効率的なシステム運用を可能にする強力な手法です。@future と Queueable Apex を理解し、それぞれの利点を活かすことで、よりパフォーマンスの高いシステムを構築できます。
• @future メソッドは基本の非同期処理
シンプルな非同期処理に最適ですが、引数の制限に注意しましょう。
• Queueable Apexの柔軟性を活用
より柔軟なデータ操作やエラーハンドリング、ジョブのチェイニングが可能なため、複雑な処理には最適です。
このガイドを参考に、非同期処理の理解を深め、より効率的なSalesforce開発に役立ててください!