Skip to content

RevFramework – Sample Scene: 06_Currency_Idempotency

Namespace: RevGaming.RevFramework.Runtime.Currency.Samples.Scenes


🎯 Purpose

Demonstrate how Idempotent Request IDs (RIDs) prevent duplicate transactions during retries, RPC resends, or unreliable network conditions.
This scene showcases the IdempotencyCurrencyService decorator in action and how it seamlessly integrates into any service stack.


🧩 What This Scene Teaches

  • How IdempotencyCurrencyService drops duplicate operations safely.
  • How to embed a Request ID (RID) in the sourceId field:
    <sourceId>|rid:<token>
    
  • How replaying a transaction with the same RID results in an instant success without reapplying side effects.
  • How to handle client retries and server resubmissions safely.
  • How to generate unique RIDs via CurrencyRequestId.New() for each operation.

🕹️ How to Use

  1. Enter Play Mode.
  2. Open the CurrencyIdempotencyPanel (F8).
  3. Select an operation type — Set, Credit, Debit, or Transfer.
  4. Enter an amount and optionally select Owner B for transfer tests.
  5. Observe the current RID token (auto-generated on scene start).
  6. Press Run Once (with RID) to perform the operation normally.
  7. Press Run Twice (replay) to resend the same RID —
    the second call will return CurOpResult.Ok immediately, skipping mutation.
  8. Press New RID to generate a new token and perform fresh operations.

🔐 Authority (Important)

This sample scene includes a CurrencyAuthorityBinder configured for single-player use:

  • CurrencyAuthorityBinder
  • alwaysTrue = true

This allows all currency mutations so the demo works out of the box.

Why this exists

RevFramework currency mutations are authority-gated by default.

  • If no authority is present, all mutations are blocked.
  • This is intentional and required for multiplayer safety.

Multiplayer note

For multiplayer or server-authoritative games:

  • Do not use CurrencyAuthorityBinder
  • Implement your own ICurrencyAuthority
  • Validate all currency mutations on the server/host

This scene uses the permissive binder only to demonstrate behaviour in a local, single-player context.


💡 Key Takeaways

  • Idempotency prevents duplicate transactions caused by network resends or retry logic.
  • IdempotencyCurrencyService caches recent RIDs per owner for replay detection.
  • The RID suffix format is always:
    |rid:<unique-token>
    
  • The system ensures consistency across all decorators — Audit, Caps, Authority, and Escrow.
  • A must-have decorator for networked economies, purchase APIs, and transaction-heavy systems.

⚙️ Stack Composition

Bootstrap: CurrencyServiceBootstrap
Service Stack:
SceneCurrencyService → CappedCurrencyService → AuditedCurrencyService → AuthorityCurrencyService → IdempotencyCurrencyService → BatchEventCurrencyService
Teaching Panel: CurrencyIdempotencyPanel

Scene Path:

Assets/RevFramework/Runtime/Systems/Currency/Samples/Scenes/06_Currency_Idempotency/


⚠️ Gotchas

  • RIDs are per owner — identical RIDs across different owners are treated independently.
  • The cache only stores recent RIDs; extremely old or unique ones will reapply.
  • The RID cache resets when the service resets (scene reload or bootstrap restart).
  • Always include a stable prefix before the RID when using shared systems (e.g., Purchase|rid:12345).
  • Idempotency doesn’t replicate across the network; ensure clients and servers share transaction IDs.
  • If this scene is running the bootstrapped service stack, removing CurrencyAuthorityBinder will cause all currency mutations to fail with Unauthorized.


Summary
Idempotency prevents chaos in distributed systems.
Run it twice — get one result.
Zero double-spends. Zero retries. Total consistency.