Skip to content

Improve FileStore read/write safety#491

Merged
satyakigh merged 4 commits into
mainfrom
filedb
Mar 31, 2026
Merged

Improve FileStore read/write safety#491
satyakigh merged 4 commits into
mainfrom
filedb

Conversation

@satyakigh
Copy link
Copy Markdown
Collaborator

@satyakigh satyakigh commented Mar 23, 2026

1. Atomic writes via write-to-temp-then-rename (EncryptedFileStore.ts)

Both save() and saveSync() now write to a temporary file (..tmp) first, then atomically rename it to the final path. Previously, writeFileSync/writeFile wrote directly to the target file.

Why it's needed: If the process crashes or is killed mid-write, a direct write can leave a truncated/corrupted file on disk. The rename operation is atomic on most filesystems — the file either has the old content or
the new content, never a partial state. This prevents data loss in the encrypted file store.

2. Guard against use-after-close (FileStoreFactory)

A closed flag was added to FileStoreFactory. Three methods now check it:

  • close() — becomes idempotent (safe to call twice)
  • emitMetrics() — no-ops if closed, preventing telemetry calls after shutdown
  • cleanupOldVersions() — no-ops if closed, and also checks existsSync(this.fileDbRoot) before reading the directory

Why it's needed: The factory sets up setInterval (metrics) and setTimeout (cleanup) timers in the constructor. If close() clears these timers but a callback was already queued on the event loop, it could fire after
close and hit errors (e.g., accessing a deleted directory or emitting metrics on a torn-down telemetry instance). The closed guard prevents that race.

3. Lock acquisition moved earlier in constructor recovery path (EncryptedFileStore.ts)

The file lock is now acquired before readFile() in the constructor, not just around the saveSync() fallback. The old code only locked when it needed to recreate a corrupted store; the new code locks for the entire read-
then-maybe-recover block.

Why it's needed: Without the lock around readFile(), another process could be writing to the file concurrently while this instance reads it, leading to a read of partially-written data. By holding the lock during the
entire constructor initialization, the instance gets a consistent snapshot of the file.

@satyakigh satyakigh requested a review from a team as a code owner March 23, 2026 18:23
@Zee2413
Copy link
Copy Markdown
Contributor

Zee2413 commented Mar 23, 2026

What's this improving and fixing? Commit message should be more detailed.

@satyakigh satyakigh changed the title Improve FileStore Improve FileStore read/write safety Mar 23, 2026
@satyakigh satyakigh merged commit 06c38e7 into main Mar 31, 2026
16 checks passed
@satyakigh satyakigh deleted the filedb branch March 31, 2026 23:04
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.

3 participants