RPC Idempotency for Gacha / Random Pack Opening¶
概念概覽
兩條設計路徑¶
核心知識¶
兩條設計路徑¶
Explicit idempotency gate:client 傳入 idempotency_key,server 在 DB 建立 key-result mapping,commit 後永久可查詢。支援 replay contract:client 若收不到回應,可用同一 key 重試並取得原始開包結果。
天然冪等(item consume + FOR UPDATE):依賴 DB 事務保證一次性消費,第二次相同操作自然因資源不足而失敗或 no-op。
天然冪等在 Gacha 的根本缺陷¶
對於 隨機性 的開包 RPC,第一次 commit 成功但回應在網路層丟失時: - 「天然冪等」:server 已扣除道具並生成結果,但 client 無法取回原始結果,只能推測狀態 - 玩家體驗:不知道開出什麼,但道具已消耗 → gameplay correctness gap,非單純 UX 問題
不能靠改文檔降級契約承諾結案¶
若文檔已承諾 explicit idempotency(replay contract),改文檔改成「天然冪等即可」屬於降級契約,不是修正。降級後恢復承諾的成本更高(已有依賴方的預期)。正確做法:補實作或明確升級至架構決策層級重新討論。
經驗教訓¶
-
隨機性(non-deterministic)RPC 必須用 explicit idempotency gate,天然冪等不夠
-
「不能靠改文檔降級契約承諾來結案」是文檔治理的核心原則
-
Explicit idempotency 增加 DB 表複雜度,但這是 gacha 場景的必要成本
常見陷阱¶
-
把「DB 事務保證一次性消費」誤認為等同於「client 可重取原始隨機結果」
-
文檔審查時用改文檔降級來快速結案,埋下後續 contract gap
-
idempotency_key 機制若未實作完整(僅 key 無 result store),replay 仍無法工作
最佳實踐¶
-
Gacha/random reward RPC 設計:必須 explicit idempotency key + result persistence
-
契約降級決策要升級至架構層,不能在文檔 PR 中靜默降級
相關概念¶
- Circuit Breaker Outcome Semantics
- ClaimMarker Pattern (PostgreSQL Idempotency)
- Dungeon Reward Dual-Path Contract
- Immutable Settlement Contract
相關視角¶
以下頁面與本概念共享主題,但從不同角度切入。保留獨立視角同時提供交叉參考:
- Twirp Admin RPC Audit Architecture — 共享:
game-server,twirp/ 獨特:admin,audit - Twirp Error Handling — 共享:
rpc,twirp/ 獨特:api,error-handling - Reward Claims Architecture — 共享:
game-server/ 獨特:reward-system,schema-design - Redis Sorted-Set TTL GC Capacity Bomb — 共享:
game-server/ 獨特:capacity-planning,event-system
來源 Sessions¶
| 日期 | Session | 貢獻摘要 |
|---|---|---|
| 2026-04-01 | 8a1ca078-1c39-4b3a-aec8-0a4b6acb84e9 | 闡明隨機開包 RPC 的冪等性設計兩條路徑,以及「天然冪等」在 gacha 場景下的根本缺陷 |