Featured image of post 10秒の障害が、全台の一斉リトライで60秒の停止に。待ち時間をずらして防ぐ【Retry Pattern】

10秒の障害が、全台の一斉リトライで60秒の停止に。待ち時間をずらして防ぐ【Retry Pattern】

コード探偵ロックの事件簿:決済プロバイダのデプロイで10秒だけ止まった API が、全インスタンスの同時リトライで60秒の停止になった。リトライの間隔を指数的に延ばしてランダムにずらし、一時的なエラーだけをやり直す(Retry Pattern)。

Featured image of post 決済APIの障害でリトライを増やすほど、停止が長引いた。呼び出しを遮断する【Circuit Breaker】

決済APIの障害でリトライを増やすほど、停止が長引いた。呼び出しを遮断する【Circuit Breaker】

コード探偵ロックの事件簿:3週間で3回、決済 API の障害で注文がすべて失敗した。リトライ回数とタイムアウトを増やすほど接続プールが埋まり、停止は長引く。失敗が続いたら呼び出しを止め、様子を見て戻す3つの状態を持たせる(Circuit Breaker)。

Featured image of post 請求サービスが落ちるたびに注文確定が止まる。直接呼ばずに掲示板に貼る【Publish-Subscribe】

請求サービスが落ちるたびに注文確定が止まる。直接呼ばずに掲示板に貼る【Publish-Subscribe】

コード探偵ロックの事件簿:マイクロサービスに分けた後も、注文サービスが在庫・配送・請求の各サービスを順に直接呼んでいたため、請求サービスの障害で注文確定が45分止まった。メッセージブローカーを挟み、送る側と受ける側が互いを知らない形にする(Publish-Subscribe)。

Featured image of post DBに書けたのに通知が消え、在庫だけ確保された注文が残る。送る内容もDBに書く【Outbox】

DBに書けたのに通知が消え、在庫だけ確保された注文が残る。送る内容もDBに書く【Outbox】

コード探偵ロックの事件簿:在庫確保を DB にコミットした直後、メッセージキューが落ちていて決済サービスへの通知が消えた。DB の更新と送るイベントを同じトランザクションで Outbox テーブルに書き、別のプロセスが後から確実に送る(Outbox)。

Featured image of post 決済のタイムアウトで在庫と配送も止まり、300件を手で戻した。手順ごとに取り消す【Saga】

決済のタイムアウトで在庫と配送も止まり、300件を手で戻した。手順ごとに取り消す【Saga】

コード探偵ロックの事件簿:在庫・決済・配送を1つのトランザクションとして扱っていたため、決済が応答しないと在庫と配送のコミットも止まり、300件の注文を週末に1件ずつ手で戻した。ステップごとに実行と補償を対で持ち、失敗したら逆順に取り消す(Saga)。

Featured image of post 帳票の種類と出力形式の組み合わせで、CSVだけ分岐を書き忘れた。漏れを型で防ぐ【Double Dispatch】

帳票の種類と出力形式の組み合わせで、CSVだけ分岐を書き忘れた。漏れを型で防ぐ【Double Dispatch】

コード探偵ロックの事件簿:帳票3種を PDF・CSV・HTML で出すフォーマッターが isa で帳票を判定し、CSV だけ1つ書き忘れた。漏れをクラス構築時のエラーにする(Double Dispatch)。

Featured image of post 500行のメソッドは1行直すと無関係な所が壊れ、テストも書けない。段に分ける【Pipeline】

500行のメソッドは1行直すと無関係な所が壊れ、テストも書けない。段に分ける【Pipeline】

コード探偵ロックの事件簿:受注処理のすべてが500行のメソッドに詰まり、1行直すと無関係な箇所が壊れる。上司には「テストを書いてから直せ」と言われたが、入口が1つではテストできない。処理を独立したステージに分け、順に流す(Pipeline)。

Featured image of post 請求金額が1円ずれ、ドル建てに円の手数料が足された。金額と通貨を一緒に持つ【Money Pattern】

請求金額が1円ずれ、ドル建てに円の手数料が足された。金額と通貨を一緒に持つ【Money Pattern】

コード探偵ロックの事件簿:税率計算の浮動小数点の丸めで請求金額が1円ずれ、翌週には USD の送金額に JPY の手数料が足された。金額を最小単位の整数と通貨の組で持ち、違う通貨どうしの計算をエラーにする(Money Pattern)。

Featured image of post 渡した料金設定を別チームが書き換え、誤請求が出た。書き換えられない形にする【Immutable Object】

渡した料金設定を別チームが書き換え、誤請求が出た。書き換えられない形にする【Immutable Object】

コード探偵ロックの事件簿:10年保守してきた料金設定クラスの属性がすべて rw で、フロントチームが受け取った割引率を書き換えて誤請求が出た。属性を ro にして書き換えを封じ、変えたいときは新しいオブジェクトを返す(Immutable Object)。

Featured image of post 同じ住所なのに等しくない、同じ物件なのに更新後は別物。比べ方を2つに分ける【Entity vs Value Object】

同じ住所なのに等しくない、同じ物件なのに更新後は別物。比べ方を2つに分ける【Entity vs Value Object】

コード探偵ロックの事件簿:不動産の物件管理で、同じ住所どうしを比べても false、名前を更新した物件を更新前と比べても false になる。住所は値で比べて不変に、物件は ID で比べる。Entity と Value Object の違いを Perl と Moo で実装します。

Featured image of post 顧客マスタを1つにしたら、営業のメール変更で配送通知の宛先まで変わった。境界を引く【Bounded Context】

顧客マスタを1つにしたら、営業のメール変更で配送通知の宛先まで変わった。境界を引く【Bounded Context】

コード探偵ロックの事件簿:3部門の顧客を1つのモデルに統合したら、営業のメール変更で配送通知の宛先まで変わった。部門ごとにモデルを分け、共有は ID と名前だけにする(Bounded Context)。

Featured image of post ポイント加算を足したら、在庫引き当てが二重に走った。起きたことを通知で伝える【Domain Event】

ポイント加算を足したら、在庫引き当てが二重に走った。起きたことを通知で伝える【Domain Event】

コード探偵ロックの事件簿:注文確定のメソッドがメール・在庫引き当て・ポイント加算を直接呼んでいて、ポイント加算を足したら在庫引き当てが二重に走った。「注文が確定した」を出来事のオブジェクトとして発行し、後続の処理は購読側に任せる(Domain Event)。

Featured image of post 月末のたびに注文の合計金額と明細が合わず、SQLで手直しする。注文を門番にする【Aggregate】

月末のたびに注文の合計金額と明細が合わず、SQLで手直しする。注文を門番にする【Aggregate】

コード探偵ロックの事件簿:EC の注文明細を外から直接書き換えられるため、月末のたびに経理から「合計金額が明細と合わない」と連絡が来て、SQL で手直ししてきた。明細の変更は必ず注文を通し、合計を自動で再計算させる(Aggregate)。

Featured image of post ルール文字列をevalで実行、括弧の閉じ忘れで3時間の本番停止。文法を組み立てる【Interpreter】

ルール文字列をevalで実行、括弧の閉じ忘れで3時間の本番停止。文法を組み立てる【Interpreter】

コード探偵ロックの事件簿:キャンペーンのルール200本以上を文字列で DB に置いて eval で実行していたため、括弧の閉じ忘れ1つで3時間の本番停止になった。ルールを式のオブジェクトの木にして評価し、構文の誤りをデプロイ前に見つける(Interpreter)。