運用・基礎知識

冪等性とは|API の再試行で二重に作らない Idempotency-Key の使い方

冪等性とは、同じ操作を何度行っても結果が 1 回分と変わらない性質です。通信が途切れたときに安全にやり直すための Idempotency-Key の使い方を説明します。


冪等性 (べきとうせい) とは、同じ操作を 1 回行っても複数回行っても、結果が変わらない性質のことです。API では、通信が途切れて応答が届かなかったときに同じリクエストを送り直しても、処理が二重に行われないことを指します。

avacast の API では、セッションの作成 (POST /v1/sessions) と発話 (POST /v1/sessions/:id/speak) が Idempotency-Key ヘッダに対応しています。このヘッダを付けておくと、再送しても二重にセッションを作ったり、同じ文を二度話したりしません。

冪等性が必要になる場面

リクエストを送ったあと、応答を受け取る前に通信が切れることがあります。このとき、呼び出し側からは「サーバーで処理されたのか」が分かりません。

  • 処理されていなければ、送り直す必要があります。
  • 処理されていたのに送り直すと、同じ処理が 2 回行われます。

GET や DELETE は、何度呼んでも結果が同じになるように作られていることが多い一方、POST は呼ぶたびに新しいものを作るのが普通です。そこで、POST にも「同じリクエストである」ことを示す鍵を付けて、サーバー側で重複を見分けます。これが Idempotency-Key です。

avacast の Idempotency-Key の決まり

項目内容
対応するエンドポイントPOST /v1/sessions、POST /v1/sessions/:id/speak
キーの長さ255 文字まで (超えると 400 invalid_request)
保持期間24 時間
同じキーで同じ内容1 回目に記録した応答をそのまま返す
同じキーで違う内容409 idempotency_conflict
同じキーの処理がまだ実行中409 idempotency_conflict
失敗した呼び出し (4xx・5xx)記録しない。直してから同じキーで送り直せる

同じキーで中身が違うリクエストに前回の結果を返すと、別の操作の結果を受け取ってしまいます。そのため、中身が違う場合は 409 で知らせます。

使い方

キーは、操作 1 回ごとに新しく作ります。UUID のように重ならない値を使うのが簡単です。再送するときは、同じキーをそのまま付けます。

サーバー (セッションの作成)

const key = crypto.randomUUID();

async function createSession() {
  return fetch('https://api.avacast.jp/v1/sessions', {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${process.env.AVACAST_API_KEY}`,
      'Content-Type': 'application/json',
      'Idempotency-Key': key,
    },
    body: JSON.stringify({ avatar_id: 'avt_xxxxxxxx' }),
  });
}

// 通信の失敗のときだけ、同じキーで送り直す
let res;
try {
  res = await createSession();
} catch {
  res = await createSession();
}

発話でも同じです。利用者の 1 回の発言に対する返事ごとにキーを作っておくと、送り直しても同じ返事を二度話しません。

キーを作るときの注意

  • 送り直しのたびに新しいキーを作ると、重複を防げません。キーは「操作」に対して 1 つです。
  • 別の操作に同じキーを使い回すと、409 idempotency_conflict になります。
  • 失敗した呼び出しは記録されないため、パラメータを直して同じキーで送り直せます。
  • 24 時間を過ぎたキーは消えます。長い時間をおいた再送は、新しい操作として扱われます。

再送の間隔の決め方は指数バックオフで再試行するで、409 の見分け方は409 Conflict の意味で説明しています。

サーバー SDK を使う場合

Node.js・Go・PHP のサーバー SDK は、セッションの作成と発話の Idempotency-Key を扱い、429・5xx・通信の失敗のときに再試行します。自分で再試行を書かずに済むため、まずは SDK を使う方法を検討してください。各 SDK の入れ方はドキュメントにあります。

よくある質問

Idempotency-Key は必ず付ける必要がありますか。

必須ではありません。付けなくても API は動きます。ただし、通信の失敗のあとに送り直す可能性があるなら、付けておくと二重のセッションや二重の発話を防げます。

同じキーで送り直したとき、応答は変わりますか。

1 回目が成功していれば、1 回目に記録した応答と同じものが返ります。セッションの作成なら、同じ session_id と client_token を受け取れます。

409 idempotency_conflict が返ったらどうすればよいですか。

同じキーを別の内容に使っていないかを確かめます。1 回目の処理がまだ終わっていない場合も 409 になるため、少し待ってから同じ内容で送り直してください。

月 30 分まで無料

カード登録なしで始められます。

API キーを発行

関連する記事

ブログ一覧へ