Repository navigation
fix(infra): make every atomic-write temp path collision-free - #200
Open
Ranjithsingh2004 wants to merge 1 commit into
Open
Ranjithsingh2004 wants to merge 1 commit into
Ranjithsingh2004 wants to merge 1 commit into
Conversation
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Every remaining bare
<target>.tmpwriter now draws its temp path from a sharedatomicTempPath()helper insrc/infra/json-file.ts:Nine write sites across eight files, each a one-line swap plus an import:
src/sessions/session-store.tssrc/auth/profiles.tssrc/infra/json-file.tssaveJsonFilesrc/core/gateway-probe.tssrc/cron/service/store.tssrc/cron/run-log.tssrc/core/tunnel/state.tssrc/agents/claude-cli/claude-config.tsNew
src/infra/json-file.test.tspins the helper and the round-trip.Why
A bare
<target>.tmpis only safe when exactly one process ever writes the target — but several of these stores are written from more than one process (the gateway and abrigadeCLI invocation both persist the session store, auth profiles, and the cron store). Two writers computing the same temp path can interleave their bytes, and the second rename then publishes a torn file: atomicity is decided by whoever renames last, not by the writer whose data survived. The repo already knew this —workspace/state.tsandagents/memory/extract.tscarry pid+timestamp temp names with comments explaining exactly this race; this PR finishes the sweep and centralizes the convention (pid separates processes, base36 ms separates writes seconds apart, a sequence counter separates same-millisecond bursts).Deliberately not touched:
collaboration-journal.ts— its temp target already embedsDate.now()+randomUUID(), so it is unique by construction;access-control/store,whatsapp/connection,exec-approvals,session-file-repair,blob-store,org-store,skill-store,workspace-store,sentinel) — behavior kept as-is.Nothing reads
*.tmp-*leftovers (verified by sweep); success renames them away, a crash leaves them inert.Tests
json-file.test.ts(6 tests): 5 000 rapid temp paths against one target are all distinct; every path is rooted at its target with the.tmp-marker and embeds the pid;saveJsonFileround-trips, survives 25 rapid rewrites with last-writer-wins and zero temp strays (directory read, no path probes); missing/empty/malformed load semantics unchanged.session-store,claude-config,oauth-refresh-persist,profile-cooldown,gateway-probe,tunnel,run-log,cron store— 84 tests, 0 failures (2 pre-existing skips).npm run typecheckclean.