v1.0.0 の歴史資料当時の説明です。現在の仕様とは異なる箇所があります。現行版の対応記事 →資料一覧へ

DEEP GUIDE 06

二重送信と同時送金

通信切断と競合があっても、一件を一件として確定する仕組みを読む。

このガイドで追う一件

送金ボタンを押した直後に通信が切れ、利用者がもう一度押します。同時に逆向きの送金も届いた場合を考えます。

コードを読む順番

以下は MiniBank v1.0.0 の確認先です。マイグレーションは順に適用されるため、関数の最終形を調べるときは後続の変更も確認してください。

  1. 1

    同じ依頼を識別する

    TransferService は冪等性キーを execute_transfer に渡します。再試行時には同じ依頼として識別できるキーを保つ必要があります。

    確認するファイルsrc/services/TransferService.ts

  2. 2

    ロックの前後で再確認する

    execute_transfer は早い段階で既存の依頼を調べ、口座を決まった順でロックした後にも再確認します。待機中に条件が変わる可能性を扱います。

    確認するファイルsupabase/migrations/20260819163038_create_execute_transfer_function.sql

  3. 3

    残高の競合を防ぐ

    画面で見た残高ではなく、ロック後に帳簿から計算した残高を基準に送金可否を判断します。

    確認するファイルsupabase/migrations/20260819163038_create_execute_transfer_function.sql

  4. 4

    成立した一件を検証する

    送金の回帰テストでは、同じキーの再送、異なる内容でのキー再利用、失敗後の取引行を確かめます。同時実行の安全性はロック順序と再確認のコードを別に読んで判断します。

    確認するファイルscripts/regression/suites/transfer.mjs

失敗時・範囲外の確認

応答が届かなかっただけでは送金の失敗と断定できません。新しいキーで送ると別の依頼になるため、同じキーで結果を確かめ、取引履歴も確認します。

ここまでで説明できること

冪等性、行ロック、トランザクションがそれぞれ別の問題を守ることを説明できます。