見出し画像

Visualforce + Apexを活用したCSVアップロード画面の課題と解決策

課題

あるお客様が別のベンダーに依頼して、VisualforceとApexを活用したCSVアップロード画面を構築しました。しかし、いくつかの問題が発生しています。

課題の詳細

  1. 期待値: 一度に最低でもCSVファイル内に一つの列(識別ID)が1000件アップロードできること。

  2. 現実: 実際には100件しかアップロードできない。

原因

  1. ファイル読み込み方法: `apex:inputFile`コンポーネントを使用し、サーバーサイドでファイルを読み込んでBlobからStringへ変換。その後、元ファイルがSHIFT-JIS形式なのでUTF-8に変換しています(SalesforceのオブジェクトはUnicodeしか格納できないため)。

  2. CPU処理タイムの上限超過: ファイルを読み込んだ後、各行の識別IDの存在チェックと有効性確認(例:識別IDに紐づくユーザ情報の有効性バリデーション)を行うため、CPU処理タイムの上限を超えてしまう(非同期処理の場合:10秒)。

  3. ガバナー制限の問題: CSVファイルに識別ID以外にオプション列(10列、一列最大4000文字)を追加する場合、HeapSizeの6MBのガバナー制限に引っかかる。

furuCRMの解決策

CPU処理タイムを減らすため、同期処理ではなく非同期処理に変更し、CSVファイルを読み込む処理や一部のバリデーションロジックをバックエンドからフロントエンド(JavaScript)に移植することが推奨されます。また、サーバーサイドへ配列の分割分(100行ずつや1000行ずつ)をポストし、サーバーサイドで処理する方法を取り入れます。この方法でHeapSizeの削減を目指します。
結果として最大1万7000件を取り込めました。

具体的な解決策

Before(従来の方法):

  1. 標準`apex:inputFile`コンポーネントを使用し、ファイルを読み込む。

  2. Apexでファイルの文字コード変換、バリデーションチェック、登録可能データの作成、リストへの挿入を行う。

  3. 最終的に非同期バッチを呼び出し(パラメータとしてListデータを使用)、分散処理を活用してInsertを行う。

After(改善された方法):

  1. `<input type="file">`を使用し、JavaScriptのFileReaderでファイルを読み込んで文字コード変換を行う。

  2. JavaScriptでバリデーション可能なロジックを実行し、バリデーションが通ったデータを配列に格納する。

  3. 配列を100行ずつや1000行ずつに分割し、サーバーサイドにポストする。

  4. サーバーサイドでは、受け取ったデータをString変数に仮に格納し、行・列をSplitして配列(ListまたはSet)に格納。

  5. 最終的に全データを読み込み、配列に書き込んで非同期バッチに流し込み、データを登録する。

メリットと注意点

メリット

  1. ガバナー制限の回避: CPU処理タイムやHeapSizeのガバナー制限を回避できます。

  2. パフォーマンス向上: フロントエンドでの処理を増やすことで、サーバーサイドの負荷を軽減し、全体的なパフォーマンスが向上します。

  3. スケーラビリティ: データを分割して送信することで、大規模データの処理が可能になります。

注意点

  1. ブラウザの操作: ファイルを読み込んだり処理中にブラウザを閉じないこと。全データの読み込みが完了し、処理完了通知が来るまで(非同期バッチが起動するまで)、ブラウザを閉じないようにする必要があります。

  2. ユーザエクスペリエンス: 処理が完了するまでユーザーは待機する必要があり、長時間の待機が発生する可能性があります。

  3. ラウンドトリップの遅延: データを分割して送信する際、ラウンドトリップが増加するため、処理時間が長くなる可能性があります。

結論

VisualforceとApexを活用したCSVアップロード画面の課題を解決するためには、非同期処理の導入とフロントエンドでの処理強化が有効です。この方法により、ガバナー制限を回避しながら、大量データの効率的なアップロードが可能となります。特に、サーバーサイドへのデータ送信を分割することでHeapSizeの制限を効果的に回避できます。ただし、ユーザーはブラウザの操作に注意し、処理完了まで待機する必要があります。また、ラウンドトリップの遅延を考慮する必要があります。この解決策を導入することで、システムのパフォーマンス向上とユーザーエクスペリエンスの改善が期待できます。

このように、フロントエンドでの処理を強化し、サーバーサイドへの負荷を軽減することで、CSVファイルの大規模データを効率的にアップロードできるようになります。ユーザーがブラウザを閉じないことを意識することも重要です。また、ラウンドトリップによる遅延を最小限に抑える工夫も必要です。

この記事が気に入ったらサポートをしてみませんか?