diff options
| author | historia <[not public]> | 2026-09-18 21:50:17 -0400 |
|---|---|---|
| committer | historia <[not public]> | 2026-09-18 21:50:17 -0400 |
| commit | 2c38386484cdb507c4687caceb37e0b963e33594 (patch) | |
| tree | b25ecf9f509a48d8126f5a4b3a0482de42676239 /internal/casino/core.go | |
| parent | e7848ea79a9a57fdf391d30c48ce649f3d2f6180 (diff) | |
| download | thehouseoficarus-2c38386484cdb507c4687caceb37e0b963e33594.tar.gz | |
fix: make slot payout and stake resolution one durable save
Diffstat (limited to 'internal/casino/core.go')
| -rw-r--r-- | internal/casino/core.go | 20 |
1 files changed, 10 insertions, 10 deletions
diff --git a/internal/casino/core.go b/internal/casino/core.go index 4177094..7ac728f 100644 --- a/internal/casino/core.go +++ b/internal/casino/core.go @@ -130,13 +130,13 @@ func (c *tableCore[P]) refundAllLocked() []Event { // settleStakeOutcome applies one wager's outcome through the wallet and // reports whether the settlement could NOT be made durable. It carries the // money-critical ordering shared by every table game (documented in -// building_guide/concurrency.md): compute the payout, pay it via -// PayStakeCover BEFORE announcing the win (that one save both credits the -// payout and removes the stakes it returns), and only then stand the hand -// down. On a persistence failure the stakes stay pending, so a later shutdown -// refund or startup recovery returns them exactly once — the payout was never -// durable, so it can never be paid on top of the refund. The caller must not -// announce a paid win and must not run the player-wide ResolveStakes. +// building_guide/concurrency.md): compute the payout, pay it via PayCredits +// BEFORE announcing the win — that one save credits the payout and resolves +// the stakes it returns, so a crash can never pay the payout AND refund the +// same stake — and only then stand the hand down. On a persistence failure +// the stakes stay pending, so a later shutdown refund or startup recovery +// returns them exactly once. The caller must not announce a paid win and must +// not run the player-wide ResolveStakes. // // payoutErr is a payout-computation error (for example an overflowed // multiplier): it is treated exactly like a persistence failure so a @@ -150,10 +150,10 @@ func settleStakeOutcome(w Wallet, payout int, stakeIDs []string, payoutErr error return false } if payout > 0 { - if err := w.PayStakeCover(payout, stakeIDs); err != nil { - return true - } + return w.PayCredits(payout, stakeIDs...) != nil } + // A zero payout is a loss: consume the stakes so recovery cannot refund a + // round that resolved. for _, id := range stakeIDs { if id != "" { w.ResolveStake(id) |
