##### 背景
- Uber,Wolt,Menuなど複数の配送サービスを管理する配送プラットフォームが開発対象
- ユーザーが「料金優先」「距離優先」などの条件を指定すると、最適な配送サービスを自動的に選択してくれる
- ユーザーが指定した時間内にドライバーが見つからない場合、キャンセル依頼を自動送信してくれる
##### 課題
- キャンセル依頼が自動送信された後、次の配送サービスに対して、ユーザーが手動で配送依頼し直す必要があった
##### 要件
- キャンセル依頼が自動送信された後、次の配送サービスに自動的に配送依頼し直してあげる
##### いくつかの設計案
- **案A: 「現在試行中の配送サービス」だけを管理する方式**: 既存の配送依頼テーブルに「今どの配送サービスを試行中か」を管理するカラムを1つだけ持たせる方式。シンプルだが、過去に試行した配送サービスがどういう状態で終わったかが残らない
- **案B: 配送サービスごとのステータスを管理する方式(採用)**: 配送依頼ステータステーブルを新規追加し、配送サービスごとのステータス(未募集/募集中/ドライバーマッチ済み/キャンセル済み)を管理する
##### 最終的に選んだ設計案
案Bを採用した。以下がその決め手。
- **障害時の状態追跡**: 案Bなら各配送サービスのステータスが独立して記録されるため、障害発生時にどのサービスがどの状態で止まったかを正確に把握できる
- **次候補の算出がシンプル**: 配送依頼ステータステーブルから「未募集」の配送サービスを取得し、ユーザーが選択した優先順に従って次候補を決める。別途キューやリストを管理する必要がない
##### 開発でハマった点・難しかった点
- **キャンセルJobと外部イベントのタイミング競合**: キャンセルJobが発火する前に、外部配送サービスから先にキャンセルされる場合があった。その際、二重にキャンセル+自動切り替えの処理が実行されてしまった。対策として、キャンセルJob実行時に「対象の配送サービスがまだ募集中か」をステータスで必ずチェックし、既に終了済みならスキップする設計にした
- **イベントログのエラーハンドリング**: 初期実装ではログ記録に失敗すると配送処理全体が打ち切られる実装になっていた。チーム内で話し合った結果、「ログは観測用データであり、ログ書き込みエラーで配送処理を止めるべきではない」となり、ログ記録に失敗した時はSentry通知のみ行いメイン処理は継続する設計に修正した