再送したら二重登録?APIの再試行を支える「冪等性」
送信中に通信が切れると、相手が処理を終えたのか分からないことがあります。そこで単純にやり直すと、同じ登録が二度行われるかもしれません。再試行を安全に扱うための冪等性と、同じ依頼を識別する仕組みを紹介します。
返事が届かないことと、処理の失敗は違う
予約を登録するアプリを考えてみます。サーバーでは登録が完了したものの、完了の返事がアプリへ届く前に通信が切れたとします。画面にはエラーが出ても、予約自体は存在します。
この状態で新しい登録として送り直すと、二件目の予約ができる可能性があります。これは説明用の仮例ですが、返事を受け取れなかったときに、送信側だけでは成否を決められない点が問題になります。
AWSの再試行と冪等性の解説でも、再試行による副作用を避けるため、同じ依頼を識別する設計が扱われています。
同じ操作を繰り返しても、結果を増やさない
冪等性は「べきとうせい」と読みます。ここでは、同じ依頼を複数回送っても、一回実行した場合と同じ効果になる性質を指します。
「通知を無効にする」は、すでに無効なら状態を変えずに終えられます。一方、「予約を一件追加する」は、そのまま繰り返せば件数が増えます。追加処理では、同じ予約依頼の再送か、新しい予約かを区別する手掛かりが必要です。
よく使われるのが、操作ごとの識別子である冪等性キーです。一つの予約依頼にキーを付け、通信の再試行では同じキーを使います。受け取る側は、そのキーの処理状況や結果を見て、重複した追加を避けます。
入力内容が同じでも、別の依頼かもしれない
同じ内容だから重複と決めると、別の問題が起きます。たとえば同じ備品を二回に分けて追加する操作は、どちらも利用者が意図したものかもしれません。
前掲のAWSの解説でも、依頼内容だけから重複を推測する方法と、呼び出す側が一意な識別子を渡す方法を区別しています。「同じ入力」と「同じ依頼」を分けることが重要です。
表が見切れる場合は横にスクロールできます
起きていること | キーの考え方 |
|---|---|
返事が届かず、同じ登録を再試行 | 同じ依頼のキーを保つ |
利用者が別の登録を新しく開始 | 新しい依頼として識別する |
同じキーなのに登録内容が違う | 意図の不一致として扱う |
表は設計の考え方です。キーを送れば、どのAPIでも自動的に重複を防げるわけではありません。受け取るAPIの対応と契約を確かめる必要があります。
キーには、保存期間とエラー時の決まりがある
具体例として、Stripeの冪等なリクエストの仕様は、同じキーによる再試行に、最初に保存したステータスコードと本文を返すと説明しています。成功結果だけでなく、保存されたエラー結果も含まれます。ただし、入力の検証段階で拒否された場合など、実行が始まらず結果を保存しないケースもあります。
同仕様では、キーが少なくとも24時間経過すると削除され得ることや、削除後のキー再利用は新しいリクエストになることも説明されています。この保持条件はStripeの仕様で、すべてのAPIに共通する保証ではありません。
長く時間が空いた場合や、どの段階で失敗したか分からない場合は、再送だけを続けず、登録結果を照会する手段が役立ちます。画面にも「完了」「失敗」「結果を確認中」を区別して伝えられると、利用者が新しい操作を重ねる前に状況を理解しやすくなります。
まとめ
通信の失敗だけでは、相手側の処理が失敗したとは言い切れません。同じ依頼の再試行と新しい操作を識別し、APIごとの保持期間やエラー時の扱いを確認することが、二重処理を避ける土台になります。
出来事を受け取る側での重複の考え方は、Webhookの基本でも紹介しています。
