aboutsummaryrefslogtreecommitdiff
path: root/building_guide/concurrency.md
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-09-20 15:35:58 -0400
committerhistoria <[not public]>2026-09-20 15:35:58 -0400
commit91b466b6923d3eb1df1658199960fe7aa6db36dc (patch)
treee8a5f308530037f9471e19e6f194177c784c36b6 /building_guide/concurrency.md
parentbab5dd653039d026eb3d4e46da7aafef7137fe7c (diff)
downloadthehouseoficarus-91b466b6923d3eb1df1658199960fe7aa6db36dc.tar.gz
feat: new placeholder world
Diffstat (limited to 'building_guide/concurrency.md')
-rw-r--r--building_guide/concurrency.md26
1 files changed, 17 insertions, 9 deletions
diff --git a/building_guide/concurrency.md b/building_guide/concurrency.md
index 40be4d9..187b942 100644
--- a/building_guide/concurrency.md
+++ b/building_guide/concurrency.md
@@ -137,10 +137,14 @@ there is no cross-file crash window to reconcile.
kind, credits as credits) and clears the ledger in one save. Graceful
shutdown (`Game.runShutdown` → `Casino.RefundAll`) and eviction use it.
-A failed save reverts the in-memory balance and ledger together, so a player
-is never charged for, credited with, or refunded a stake that is not durable.
-On `persistence.ErrDurabilityUncertain` a wager keeps its in-memory debit and
-pending entry, because the visible file already carries both.
+A save failure **before replacement** reverts the in-memory balance and
+ledger together. On `persistence.ErrDurabilityUncertain`, every wallet
+operation (wager, payout, stake resolution, refund) instead keeps the applied
+balance and ledger, because the visible file already carries both. The wallet
+logs the storage fault and reports the operation as applied so callers do not
+retry a payout or refund a resolved stake. This does not promise survival of
+a subsequent OS/power crash; it prevents a later save from overwriting the
+visible result with reverted memory.
At startup (`game.New` → `recoverPendingWagers`, `internal/game/money.go`)
any stake still listed in a character's `PendingWagers` is refunded: a listed
@@ -160,8 +164,9 @@ at a cost of ~1,400 lines of engine code and ~2,000 lines of tests.
With the crash-consistency bar deliberately lowered to "a rare ungraceful
stop may lose or refund one in-flight stake, and must never double-pay", the
single atomic character save is sufficient: a listed pending stake is
-refunded, and a settlement whose save fails simply leaves the stake pending
-and the win unannounced (never paid on top of the refund). Do not reintroduce
+refunded, and a settlement whose save fails before replacement leaves the
+stake pending and the win unannounced (never paid on top of the refund).
+Post-replacement uncertainty follows the applied-state policy above. Do not reintroduce
a second money store, per-record ordering, or an operator-inspection queue
without an explicit decision to restore bank-grade guarantees.
@@ -178,9 +183,12 @@ payouts) clamp at the cap and log rather than wrap.
Account and character lifecycle operations (create, rename, delete, purge)
are single journal transactions (`internal/persistence/txn.go`): a journal
entry with before-images is written durably BEFORE any file changes, the
-operations apply, and the journal is removed at the commit point. Any
-failure rolls back every applied operation; a crash mid-commit is rolled
-back at the next startup by `persistence.Recover`.
+operations apply, and the journal is removed at the commit point. Deletes
+sync their parent directory; moves sync both affected directories (once if
+they are the same). Rollback also syncs deletions, including retries where
+the file is already absent, before retiring the journal. An apply failure
+attempts rollback; if rollback fails, the journal stays for recovery. A crash
+mid-commit is rolled back at the next startup by `persistence.Recover`.
Characters carry a stable UUID (`player.Player.ID`) and owner field
(`player.Player.Account`), assigned at creation and backfilled at first