Skip to content

perf+fix: cache getKnownRigs() and atomic rigs.json write#3466

Closed
oscarhermoso wants to merge 2 commits intogastownhall:mainfrom
oscarhermoso:fix/rigs-json-perf-and-atomicity
Closed

perf+fix: cache getKnownRigs() and atomic rigs.json write#3466
oscarhermoso wants to merge 2 commits intogastownhall:mainfrom
oscarhermoso:fix/rigs-json-perf-and-atomicity

Conversation

@oscarhermoso
Copy link
Copy Markdown

Summary

Changes

  • src/daemon/Daemon.ts — memoize getKnownRigs() result keyed to heartbeat generation; invalidate after each tick
  • src/daemon/Daemon.ts — write to rigs.json.tmp then fs.renameSync to rigs.json

Test plan

  • Run gt daemon with 3+ rigs; confirm rigs.json is always valid JSON during a heartbeat tick (no zero-byte window)
  • Add a log statement to getKnownRigs() and confirm it is called once per tick rather than once per rig

🤖 Generated with Claude Code

oscarhermoso and others added 2 commits April 1, 2026 19:17
getKnownRigs() reads mayor/rigs.json on every call; it was invoked 10+
times per heartbeat tick across daemon.go, lifecycle.go, checkpoint_dog.go,
and main_branch_test_runner.go.

Add a knownRigsCache/knownRigsCacheValid pair on Daemon (heartbeat-goroutine-
only, no sync needed). heartbeat() now calls loadKnownRigsFromDisk() once at
tick start, populates the cache, and clears it via defer at tick end.
getKnownRigs() returns the cached slice when valid, otherwise falls back to
loadKnownRigsFromDisk() for callers outside the heartbeat loop (e.g. startup
checkAllRigsDolt).

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Replace os.WriteFile with temp-file + os.Rename in SaveRigsConfig so
concurrent readers never observe a partially-written file. Also add a
one-shot retry in LoadRigsConfig to recover from any remaining torn
reads, and update the two doctor workspace_check.go fix paths to use
the same atomic pattern.

Adds unit tests: concurrent writers stress test and retry-on-torn-read test.

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
@github-actions github-actions bot added the status/needs-triage Inbox — we haven't looked at it yet label Apr 1, 2026
jw409 added a commit to jw409/gastown-upstream that referenced this pull request Apr 2, 2026
…writes

Cache the result of getKnownRigs() within each heartbeat tick to eliminate
10+ redundant reads of mayor/rigs.json per cycle. The cache is invalidated
at the start of each heartbeat so changes are picked up between ticks.

Replace direct os.WriteFile calls for rigs.json in the doctor package with
util.AtomicWriteFile (write-to-temp-then-rename) to prevent concurrent
readers from seeing zero-byte or partial content.

Fixes gastownhall#3466
@oscarhermoso
Copy link
Copy Markdown
Author

oscarhermoso commented Apr 2, 2026

This should be reimplemented with

// AtomicWriteJSON writes JSON data to a file atomically.

or just accept #3489

@oscarhermoso
Copy link
Copy Markdown
Author

Closing in favour of #3489

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

status/needs-triage Inbox — we haven't looked at it yet

Projects

None yet

1 participant