一括処理の部分失敗は粒度を決める — 全件失敗にせずスキップ+件数返却で集計する
バックエンド
設計判断
非同期処理
判断
原則
複数レコードをまとめて処理する一括操作で「対象の一部が見つからない/個別に失敗する」ケースの扱いは、暗黙に決めず粒度を明示する。素朴に「1件でも欠けたら例外で全体中断」にすると、バッチ/チャンク単位では1件の欠損が数百件の正常分を巻き添えにし、本来更新できた分まで未処理になる。
判断基準
- 個別失敗を許容したい一括操作では、欠損/失敗レコードはスキップして警告ログに残し、見つかった分の処理を続行する。作業対象の id 集合を「実在した分」に絞り込んでから後続処理(集計・索引更新・履歴)に渡す(欠損 id を後段に渡すと無駄や別エラーの原因)。
- 処理メソッドは「実際に処理した件数」を返す設計にし、呼び出し元(ワーカー/オーケストレータ)が success と failed を正確に集計できるようにする。戻り値が無いと、呼び出し元はチャンク全体を success と数えるか、例外で全 failed にするかの二択になり実態とズレる。
- 「全件成功か全件失敗か」の all-or-nothing が要件なら、それは明示的な選択として残す(部分コミットの不整合や UX を踏まえて決める)。
共有メソッドの落とし穴
同じ処理メソッドを「非同期バッチ経路」と「同期のユーザー操作経路(HTTP)」の両方から呼んでいる場合、失敗セマンティクスの最適解が経路で異なることがある。同期経路は「一部欠損なら即エラーで知らせる」厳格さが好まれ、バッチ経路は「欠損はスキップして残りを進める」寛容さが要る。片方に合わせて変えると他方の振る舞いも変わるため、両経路で同じでよいか、呼び出し元ごとに分けるか(引数フラグ等)を意識して決める。
検証
一部だけ存在しない id を混ぜて呼び出し、(1) 欠損分がログに出る、(2) 見つかった分は更新される、(3) 戻り値の件数が実処理数と一致し、呼び出し元の failed 集計が欠損数と一致することを確認する。