if 文の中の 36 や 3600 が、トライアル日数なのかタイムアウト秒数なのか誰にも分からない。名前付き定数と Moo の属性で数値に意味を持たせる(Magic Numbers)。Perl で実装します。
コードのにおいを嗅ぎ分けて直していく、バーを舞台にした全12話の目次。困りごと別の一覧から、読みたい話を選べます。
コード探偵ロックの事件簿:共通の Gateway が返す商品詳細は、モバイルには重いうえに足りない。Web 用とモバイル用に別々の窓口を置き、それぞれの形で返す(Backends for Frontends)。
コード探偵ロックの事件簿:フロントエンドが4つのマイクロサービスを直接呼んでいたため、Order サービスのベースパスが3か月で6回変わり、そのたびにエンドポイント一覧とコードを直した。窓口を1つ置き、ルーティング表で変更を吸収する(API Gateway)。
コード探偵ロックの事件簿:基幹システムの刷新を1つのフラグで一斉に切り替える計画だったが、演習で注文は通ったのに未実装のキャンセルまで新系へ送られ、窓口を通らない旧系直結の処理も残っていた。機能ごとに少しずつ移し、移行の判断と翻訳を分ける(Strangler Fig)。
コード探偵ロックの事件簿:外部倉庫 API の略語の項目名を社内コードがそのまま使い、値が1つ増えるだけで PR が7本立った。境界に翻訳の層を置く(Anti-Corruption Layer)。
コード探偵ロックの事件簿:出荷指示キューが1台では締切に間に合わず4台に増やしたら、同じ出荷の予約が37件重複した。複数のワーカーで同じキューを取り合いつつ、冪等キーで副作用を1回に抑え、成功してから ack する(Competing Consumers)。
コード探偵ロックの事件簿:失敗したメッセージをキューに戻し続けていたため、注文確認メールの送信キューが7時間止まり、826件が詰まった。試行回数を数え、上限を超えたら別のキューに移して通知し、直した後で再投入する(Dead Letter Queue)。
コード探偵ロックの事件簿:ヘルスチェックは緑なのに、検索インデックスの準備前で画面が 500 を返した。live・ready・details を分けて答える(Health Check)。
コード探偵ロックの事件簿:デプロイのたびにワーカーが全テナントのデータを先読みし、起動に42秒、メモリは 1.3GB を超えていた。実際に触るのはその一部だけ。重いデータは必要になるまで読まず、一覧の経路だけは明示的に先読みする(Lazy Loading)。
コード探偵ロックの事件簿:注文 API が1リクエストごとに DB 接続を作って捨てていたため、ピーク時の p99 が 350ms に跳ねた。接続をプールで使い回し、返すときに状態をリセットし、例外でも必ず返却する(Object Pool)。
コード探偵ロックの事件簿:注文 API・商品検索 API・レポートバッチが1つの DB コネクションプールを共有していたため、月末のバッチの暴走でサイト全体が30分止まった。機能ごとに使える接続を分け、上限に達したら待たずに断る(Bulkhead)。
コード探偵ロックの事件簿:通常 500 req/s の注文 API に 5,200 req/s が押し寄せて止まった。クライアントごとに流量を制限し、超えたら 429 を返す(Rate Limiting)。
コード探偵ロックの事件簿:在庫照会 API が遅れたときの代わりの経路が、遅延の原因と同じ DB を直接読んでいたため、30秒で済むはずの停止が30分の全面停止になった。キャッシュ・既定値・機能の縮退の順に、主経路と独立した代わりを並べる(Fallback Pattern)。
コード探偵ロックの事件簿:在庫照会 API が55秒かかる状態が30分続き、その間注文処理が止まった。タイムアウトは設定しておらず、HTTP::Tiny の既定の60秒のままだった。接続と読み取りの上限を分け、呼び出し先ごとに値を決める(Timeout)。