Skip to content

Guard fileStorage against concurrent writers with a heartbeat lock and unique temp files - #547

Merged
zackbart merged 1 commit into
mainfrom
fix/followup-filestore
Sep 16, 2026
Merged

zackbart merged 1 commit into
mainfrom
fix/followup-filestore

Conversation

@zackbart

Copy link
Copy Markdown
Owner

Closes #542.

  • fileStorage acquires an exclusive <path>.lock before loading. A second instance or process on the same path fails at construction naming the holder instead of overwriting a stale snapshot.
  • The holder refreshes the lock every 15 s; a heartbeat older than 60 s expires regardless of pid, so a container restart that reuses a pid cannot wedge the deployment. Within the same host and pid namespace (Linux boot id plus pid namespace, hostname elsewhere) a dead pid is reclaimed immediately, and an in-process registry tells a previous incarnation apart from a second opener.
  • Stale-lock recovery is serialized through an age-limited .lock.reclaim guard. Writes prove ownership before changing state and before rename; reads use the loaded snapshot.
  • Each write uses a unique, exclusively created temp file. The JSON format is unchanged. The returned store has close(); process exit also releases the lock.

Full npm run check passes on this branch.

🤖 Generated with Claude Code

…d unique temp files

fileStorage now acquires an exclusive <path>.lock before loading, so a second
instance or process on the same path fails at construction naming the holder
instead of overwriting a stale snapshot. The holder refreshes the lock every
15 seconds and a heartbeat older than 60 seconds expires regardless of pid,
so a container restart that reuses a pid cannot wedge the deployment; within
the same host and pid namespace a dead pid is reclaimed immediately, and an
in-process registry tells a previous incarnation apart from a second opener.
Stale-lock recovery is serialized through an age-limited guard. Writes prove
ownership before changing state; reads use the loaded snapshot. Each write
uses a unique exclusively created temp file. The JSON format is unchanged and
close() releases the lock, as does process exit (#542).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@zackbart
zackbart merged commit 29a630d into main Sep 16, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Guard fileStorage against concurrent writers sharing one state file

1 participant