diff options
| author | historia <[not public]> | 2026-09-16 19:57:45 -0400 |
|---|---|---|
| committer | historia <[not public]> | 2026-09-16 19:57:45 -0400 |
| commit | 6ef40a5739f1723ec26cc32dfc48fe764f776dca (patch) | |
| tree | e215a4dc96ea639bcea07bb589aae3e31c3609bb /internal/game/game.go | |
| parent | 1dad15698845d370e998f7cc5feb8aece3fab58f (diff) | |
| download | thehouseoficarus-6ef40a5739f1723ec26cc32dfc48fe764f776dca.tar.gz | |
fix: durable payouts survive journal failure, cap bank withdrawals, hash passwords off the owner loop.
Diffstat (limited to 'internal/game/game.go')
| -rw-r--r-- | internal/game/game.go | 14 |
1 files changed, 14 insertions, 0 deletions
diff --git a/internal/game/game.go b/internal/game/game.go index 096e070..7255042 100644 --- a/internal/game/game.go +++ b/internal/game/game.go @@ -291,6 +291,20 @@ func (g *Game) HandleSessionOnOwner(sess *net.Session, input string) { if g.isShuttingDown() { return } + // Password work is expensive (Argon2id, ~64 MiB and tens of + // milliseconds per call) and must never run on the owner goroutine: + // the owner serializes every command and tick, so a burst of logins + // would stall the whole world. Verify/hash on the caller's connection + // goroutine, then submit one owner task for the (cheap) state + // transition. + switch sess.State { + case net.StatePassword: + g.handlePasswordOffOwner(sess, input) + return + case net.StateNewAccount: + g.handleNewAccountOffOwner(sess, input) + return + } g.RunOnOwner(func() { // Re-checked at task execution: the flag may flip between // submission and execution, and RunOnOwner must never fall back |
