Repository navigation
fix(core): fsync atomic writes and keep an unreadable video state recoverable - #7484
Open
aniruddhaadak80 wants to merge 1 commit into
Open
aniruddhaadak80 wants to merge 1 commit into
aniruddhaadak80 wants to merge 1 commit into
Conversation
Merged
2 of 4 tasks
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.
Summary
video-state.jsoncould come back as a file full of NUL bytes after a hard power loss, and the next run silently replaced it with an empty state — losing every check, snapshot, revision and file record for that production.Two causes, both fixed here:
writeTempSiblingwrote the temp file withwriteFileSync(..., { flag: "wx" })andpublishSiblingrenamed it over the target. Nothing fsynced the data before the rename, so the name could reach the disk before the bytes did — a power cut left the target with the new size and zero-filled contents.updateStatecaughtSyntaxError, moved the file aside to.invalid-<uuid>and continued with an empty state.Fix
packages/core/src/atomicFile.tswriteTempSiblingnow writes through a file descriptor andfsyncs it before the rename, so the rename can never outrun the data: a power cut leaves only an unreferenced temp file, never a NUL-filled target.createDirectlyfsyncs the created file as well, and the parent directory is synced after a sibling publish (skipped where the platform cannot sync a directory).fssurface used by these helpers now carriesopenSync/fsyncSync/closeSync.packages/studio-server/src/history/videoState.tsVideoStateCorruptErrorthat names the state path, the backup path and the recovery steps..hyperframes/video-state.json.bak..invalid-<uuid>, and a warning names the copy. With no readable backup the update fails instead of rewriting anything, so the records are still there to recover.Tests
packages/core:vitest run src/atomicFile.test.ts→ 32 passed, 8 skipped. New cases cover fsync-before-rename ordering, directory sync, and the direct-create path.packages/studio-server:vitest run src/history/videoState.test.ts→ 11 passed, 1 failed; the failure is the pre-existing WindowssymlinkEPERM case (it fails identically on the unmodified parent commit).tsc --noEmitclean inpackages/coreandpackages/studio-server.Closes #7417