起こったこと
CSVデータアップロード機能をPHP(Laravel)で作成していた。
1万件以上のレコードを持つ大容量のCSVデータをアップロードし、DBにデータを保存しようとした際、開発環境でタイムアウトエラーが発生してしまい、正常なアップロードが出来なかった。
しかし、DBにはデータがアップロードされていたため、「エラーが発生しているのにトランザクションがロールバックされていない」問題が発生してしまった。
原因
CloudFrontはタイムアウト(504 gateway timeout)をクライアントにレスポンスしているが、PHPのプロセスが裏側で動いており、トランザクションが正常にコミットされていたためDBにデータが登録されていた。
解決策
大容量のCSVデータ自体は時間がかかっても正常に登録されることが分かったので、DBの該当テーブルに新しくフラグを追加し、
「処理中(デフォルトの値)」
「成功(コミットした場合更新)」
「失敗(ロールバックした場合更新)」
の3種類の値を入れられるようにした。
504エラーが出た際に画面を開きなおしてもらい、フラグの値に応じて現在の状況をメッセージで非同期に表示できるようにした。
これにより、504エラーが出た際裏側でアップロードが続いていたとしても対応することが出来、たとえ他のエラーが起きてcatchブロックに入ったとしても「失敗」フラグが立つためメッセージにその旨が表示されるようになる。
終わりに
504エラーが発生した時点で処理が中断されるとばかり思いこんでいたため、盲点だった。
なぜロールバックされないのか、トランザクションに問題があるとばかり考えて調査していたが、完全に見当違いだった。
今後は視野を広く持ち、様々な可能性を考えていきたい。