同一パスに複数の生成元(driver)が書きうる成果物を選択ポインタ(meta)で切り替える設計では、ポインタの確定を本体処理の成功確認後に遅延させる
設計判断
信頼性
エラーハンドリング
判断
原則
一つの名前(ファイル名・キー等)に対して複数の異なる方式(driver)で生成できる成果物があり、どちらの方式で生成されたかを別途のメタデータ(選択ポインタ)で記録し、下流処理(変換・レンダリング等)がそのポインタを見て入力を一意に選ぶ設計で、非同期な本体処理が途中失敗しうる場合の安全な確定タイミング。
問題の型
本体処理(録画・変換等の実際の成果物生成)の完了を待つ finally/try-catch の中で、「終了処理自体が例外を投げなければ選択ポインタを新しい値へ書き換える」実装は、「終了処理自体は成功したが、本体処理の中身は失敗していた」ケースで事故る。例: デバイスへの操作シーケンスが途中で失敗しても、後向きのクリーンアップ処理(リソースの終了処理等)は単体では正常に完了するため、その完了を「全体成功」と誤解してポインタを更新してしまうと、実際には中途までしか完成していない成果物を「有効な完成成果物」として以降の処理が選ぶようになる。同一パスを上書きする方式だと、失敗した新しい方が既にディスク上に存在してしまうため、古い良い成果物が残っていてもポインタが新しい方を指し続けると、古い良い成果物は存在しても事実上到達不能になる。
判断基準
- ポインタを書き換える条件を「終了処理が例外を投げないこと」ではなく「本体処理が中断なく完了したこと」に専属させる。本体処理の成否を示すフラグ(例: try ブロックの最後に代入するブール値)を終了処理へ明示的に渡し、ポインタ書き換えはそのフラグが true のときのみ実行する。
- 本体処理が例外を投げた場合、JS/TS の try-finally は finally が例外を投げなければ try の元の例外が finally 完了後に自動的に再度スローされる。この性質を利用すれば、「終了処理が例外を投げなくても、元の本体失敗は自動的に呼び出し元へ伝播する」ことを前提に、周辺のクリーンアップ処理(古い別ポインタの削除等)はさらに後ろ(finally ブロックの外)に置くと、本体失敗時は自動的に到達しなくなり別途の保護ロジックが不要になる。
- 同一 driver 内での再生成失敗(新しい出力が同一パスを上書きするケース)はこの対策だけでは完全には守れない点に注意: 成果物ファイル自体はすでに上書きされていることがある。このパターンが確実に守るのは「別パスへ書く別 driver 間の切り替え」で、同一パスへの上書きを伴う同一 driver の再生成は別途の対策(一時パスへ書いて成功後のみ rename する等)が必要。
検証方法
本体処理を意図的に失敗させ、(1) 失敗前に既に別方式の良い成果物が存在していた場合、ポインタがその良い成果物を指し続けること、(2) 元の例外が呼び出し元に正しく伝播すること、(3) 周辺のクリーンアップ処理(旧成果物削除等)に到達しないことを確認する。