The state is copied by hand, and the proxy waits out a restart

Two-thirds of a ledger replay was structuredClone; a recursive copy of
plain data does the same work in a fraction of the time, so a server
boot — every ledger replayed — is half as long, and the automaton's
lookahead is quicker with it. Caddy now holds a request for up to
thirty seconds while the game restarts, dialing every quarter second,
so a visitor who lands during a deploy waits instead of meeting a 502.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jm2auWk6RP71CjaAb4FMoG
This commit is contained in:
Eric Wagoner
2026-09-05 20:41:02 -04:00
co-authored by Claude Fable 5.1
parent 0821b8f7c7
commit c7edfa74ad
2 changed files with 19 additions and 3 deletions
+15 -1
View File
@@ -4068,8 +4068,22 @@ export function activePlayer(state: GameState): PlayerState {
return state.players[state.turn.activeIndex]!;
}
/** The state is plain data literals, arrays, numbers (Infinity
* included), strings, booleans, and the odd undefined so a recursive
* copy serves, and runs several times faster than structuredClone. Every
* command clones once, and a server boot replays every ledger. */
function clone(state: GameState): GameState {
return structuredClone(state);
return deepCopy(state);
}
function deepCopy<T>(value: T): T {
if (Array.isArray(value)) return value.map(deepCopy) as T;
if (value !== null && typeof value === "object") {
const out: Record<string, unknown> = {};
for (const key in value) out[key] = deepCopy((value as Record<string, unknown>)[key]);
return out as T;
}
return value;
}
/** Everything an eliminated wizard leaves behind goes with them.