Repository navigation
fix(studio-server): undo and redo on Windows wait out a briefly held file - #6559
Conversation
261aa8c to
f8e6191
Compare
Edit accuracy: accurate 271 (base branch 271), smooth 152 of thoseThe gate passes. Quarantined, measured but not gated (0) |
There was a problem hiding this comment.
Verdict: APPROVE · 0 blocker · 0 important · 0 nits · head f8e61918
The rebase only adds new context from main. The PR patch is otherwise the same as 9400172c plus the oxfmt fix. No relative utils/renameWithRetry or utils/removeScratch imports are left after #6550. All Actions runs at this head are green, including Build's size budget and the Windows lanes.
Scope
Read the full diff. Checked every blobStore rename path and its projectHistory callers (keep, then rmSync; writeTo with assertWritable). Checked the move to the core subpath (exports, package-subpaths, cli bundling through noExternal). The atomicFile behavior change (Windows only, about 1.3 s backoff) is described in the body.
What
Undo and redo on Windows no longer fail when another process (an editor, the preview, an antivirus scan) holds a project file open for a moment. History's blob store now retries its renames the way the engine already does, through one rename helper that now lives in core.
Why
Windows refuses a rename over a file that another process has open, with EPERM, EBUSY or EACCES, usually for a few milliseconds. The history blob store renamed with plain
rename/renameSync, so one held file failed the whole undo or redo. The engine already had a retrying helper, and core's atomic write kept a second, shorter copy of the same idea.Related work
None.
How
renameWithRetry/renameWithRetryAsyncandremoveScratchmove frompackages/engine/src/utilstopackages/core/src, exported as@hyperframes/core/rename-retryand@hyperframes/core/remove-scratch. The engine imports them from core, and its public re-exports inindex.tsstay the same.blobStore.tsroutes its four renames (restore copy, put, keep's move-aside and temp rename) through the helper.atomicFile.tsdrops its private retry loop and uses the shared helper. One behavior change: that write now retries only on Windows, with the engine's longer backoff (about 1.3 s in total, instead of 100 ms). On macOS and Linux a busy-rename error is real, so it is thrown at once.Not changed: the other raw renames in history (
pruneHistories.tsmoving a history to trash,videoState.tswriting its state file). They are not on the undo/redo path.Test plan
blobStore.test.ts, run as win32: a mocked rename throws EPERM twice, then succeeds. Both the restore write andputsucceed on the third attempt. Against the oldblobStore.tsboth tests fail with EPERM.atomicFile.test.tsbusy-target case runs as win32 and expects the helper's 8 attempts.ffprobe.test.ts, which needs an installed ffprobe and the HDR PNG fixture; this change does not touch it.check:package-subpaths,check:workspace-contracts,check:package-cycles, oxlint and oxfmt pass.