mirror of
https://github.com/prosolis/gogobee.git
synced 2026-07-15 16:42:41 +00:00
Audit pass addressed concurrency races, crash-recovery double-pay risks, and non-determinism in tie tallying. CRITICAL — concurrency - coopResolveFloor now acquires advUserLock for every party member (sorted by UserID) before mutating state, so concurrent !coop fund / vote / giftvote commands serialize against the scheduler. CRITICAL — crash idempotency - Add coop_dungeon_runs.last_resolved_day and coop_dungeon_members.member_payout columns (with migration entries) for crash-resume tracking. - Skip resolution only if last_resolved_day >= day AND status is terminal; otherwise re-enter and finish via idempotent operations. - On resume detection (event already has outcome), reuse the saved roll instead of re-rolling — prevents different outcomes on retry. - claimCoopMemberPayout / claimCoopBetPayout: atomic UPDATE...WHERE col IS NULL pattern. Each member/bet can only be paid once; retries are silent no-ops. - createCoopEvent now INSERT OR IGNORE — idempotent on retry. - last_resolved_day is set as the FINAL write per floor. HIGH — bugs - Lazy-create floor event in resolver if missing — covers crash window between lockCoopRun and the original createCoopEvent. - coopTallyVote sorts tied winners alphabetically before fallback (was non-deterministic via Go map iteration). - Removed dead day-1 wipe combat-action refund block — refund check was always false because midnight reset clears state before resolution. LOW - Log slog.Error on malformed JSON in parseCoopVotes / parseCoopFundingMap instead of silently dropping data. Tests - Tally test extended to assert determinism across 50 runs (catches map-iteration leaks). - Added coverage for new tie-with-leader-vote-outside-winners case. - Idempotency-guard sanity check on LastResolvedDay vs CurrentDay. Race detector: clean. Full suite: green. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
10 KiB
10 KiB