RevFramework – Sample Scene: 06_Currency_Idempotency¶
Goal¶
Teach retry-safe currency mutations using request identity:
Reason / SourceId / RID → real service mutation → same-RID replay → compare results and live balances.
What This Scene Demonstrates¶
This scene shows idempotency as observed service-stack behaviour.
The flow is:
Owner A → optional Owner B → ICurrencyService → operation with sourceId|rid:<token> → first call → same-RID replay → CurOpResult
- Owner A is the primary wallet being mutated
- Owner B is only required for Transfer A → B
- RID is appended to SourceId as
|rid:<token> - Run Once sends one real mutation request
- Run Twice sends the same request twice with the same RID
- The panel compares first-call and replay results
- Live balances show whether the second call mutated again
Idempotency is service-stack behaviour, not a panel feature.
The service result is truth.
What To Look For¶
Use the CurrencyIdempotencyPanel to observe replay behaviour from the public API side.
-
Bindings
-
Owner A is required for all operations
- Owner B is required only for Transfer
-
Service shows the resolved
ICurrencyServicestack -
Reason / Source / RID
-
Reason explains why the mutation happened
- Source identifies what triggered it
- RID identifies this request instance
- Effective SourceId shows the actual
sourceId|rid:<token>value sent to the service -
New RID creates a fresh request identity
-
Operation
-
Set writes an absolute balance
- Credit adds funds
- Debit removes funds
- Transfer moves funds from Owner A to Owner B
-
These are real service calls, not fake replay simulations
-
Replay
-
Run Once sends one request with the current RID
- Run Twice sends the same request twice with the same RID
- Compare the first and second
CurOpResult - Check live balances to see whether the second call changed state again
Sample Scope¶
This scene covers:
- Building a RID-bearing SourceId
- Running real Set / Credit / Debit / Transfer calls
- Replaying the same operation with the same RID
- Comparing first-call and replay results
- Verifying observed behaviour through live balances
- Demonstrating the public-API limitation of hostile consumer panels
This scene does NOT cover:
- Inspecting internal decorators
- Proving idempotency composition through reflection
- Backend request stores
- Persistent RID caches
- Distributed transaction systems
- Multiplayer replication or networking
Those are service composition or project-level concerns.
Authority Note¶
This scene may include a permissive sample authority setup so it runs without additional configuration.
Networking Reminder¶
RevFramework does not include networking.
For multiplayer projects, retry requests must be routed through your own networking and authority layer. Idempotency helps avoid duplicate effects, but server/host validation is still your responsibility.
How To Use¶
- Enter Play Mode.
- Toggle the
CurrencyIdempotencyPanelwithF8. -
Confirm the top bindings:
-
Owner A is assigned
ICurrencyServiceis resolved- Owner B is assigned if testing Transfer
- Check Reason / Source / RID.
- Use New RID if you want a fresh request identity.
- Select a currency.
-
Select an operation:
-
Set
- Credit
- Debit
- Transfer
- Enter an amount.
- Press Run Once to send one request.
- Press Run Twice to send the same request twice with the same RID.
-
Compare:
-
first
CurOpResult - second
CurOpResult - live Owner A / Owner B balances
Failure Behaviour¶
Failures are shown through dependency messages, disabled replay state, or returned CurOpResult values.
Common causes:
-
Play Mode required
-
Idempotency is observed through live mutations and same-RID replay
-
Fix: enter Play Mode
-
Service missing
-
No
ICurrencyServicewas resolved -
Fix: add
SceneCurrencyService, addCurrencyServiceBootstrap, or publish a composed service -
Owner A missing
-
Owner A is required for all tests
-
Fix: assign Owner A or tag the player GameObject as
Player -
Owner B missing for Transfer
-
Transfer A → B needs a target wallet
-
Fix: assign Owner B or choose Set, Credit, or Debit
-
No RID token
-
Replay needs stable request identity
-
Fix: enter a RID token or press New RID
-
No currencies bound
-
No
CurrencyDefinitionassets are available -
Fix: assign currencies in the Inspector or provide a
CurrencySet -
Invalid CurrencyId
-
The selected
CurrencyDefinitionhas an invalid Id -
Fix: correct the CurrencyDefinition asset
-
Invalid amount
-
Credit, Debit, and Transfer require an amount greater than zero
-
Fix: enter a positive amount
-
Second call mutates again
-
Same-RID replay did not suppress the duplicate effect
-
Fix: check that idempotency is composed into the service stack and that the RID-bearing SourceId is identical
-
Replay returns failure
-
The service rejected one or both calls
- Fix: check the code/message, operation arguments, balance, authority, caps, escrow, and service composition
Behind The Scenes¶
The panel uses only public Currency APIs:
-
CurrencyResolve.ServiceFrom -
resolves the active
ICurrencyService -
SourceId convention
-
appends
|rid:<token>to the supplied source id -
ICurrencyService -
SetBalance CreditDebitTransfer-
GetBalance -
CurOpResult -
Success CodeMessage
The panel does not inspect decorators.
It cannot directly prove idempotency is present.
It observes first-call vs same-RID replay behaviour through public service results and live balances.
Key Takeaway¶
RID identifies a specific request instance.
Same RID means “this may be a retry.”
If idempotency is composed correctly, replay should not apply the mutation twice.