Skip to content

fix(producer): try Windows junctions before copying cached frames - #3740

Merged
jrusso1020 merged 1 commit into
mainfrom
fix/windows-frame-staging-links
Sep 7, 2026
Merged

fix(producer): try Windows junctions before copying cached frames#3740
jrusso1020 merged 1 commit into
mainfrom
fix/windows-frame-staging-links

Conversation

@jrusso1020

Copy link
Copy Markdown
Collaborator

Local Windows renders currently force a recursive copy of every extracted frame, bypassing the existing link fallback. Let local renders use directory symlinks, then a Windows junction after a privilege denial, then copy if junctions are unavailable. Distributed plans continue requesting physical copies. Disk errors and stale-destination recovery retain their existing behavior.

Successor to @sidorovanthon’s #2314, with co-author credit. Junction attempts are explicitly Windows-only, preserving POSIX fallback behavior.

Validation: a regression running the actual executeRenderJob call failed before because Windows requested eager copying; it passes after. Locally, 226 tests pass, with the real-Windows junction case skipped on macOS. Producer typecheck, lint/format and classification pass. The targeted Windows CI step runs a real junction test: only the first symlink privilege denial is simulated, frame reads use the actual junction, and deleting the junction must preserve the source. A separate test verifies distributed copies remain readable after removing their source cache. Windows CI is required before merge.

Follow up Anton Sidorov’s junction staging contribution in #2314 on current main.

Co-authored-by: Anton Sidorov aka anticodeguy <a@anticodeguy.com>

@terencecho terencecho left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving at 655553e714e1e307f7868979aca7b8645066f354.

3-tier fallback (linkOrCopyFrameDir in packages/producer/src/services/render/shared.ts). Tier 1 symlinkSync(src, dest, "dir") runs everywhere; catches only EPERM/EACCES/UNKNOWN, rethrows everything else. Tier 2 tryWindowsFrameJunction is a no-op on non-Windows and attempts symlinkSync(src, dest, "junction") on Windows, treating 7 capability codes (EPERM/EACCES/UNKNOWN/EINVAL/ENOSYS/EOPNOTSUPP/ENOTSUP) as "junction unavailable → false" so tier 3 cpSync runs. Every non-capability junction error propagates — the ENOSPC test asserts cpSync is not called in that path.

Caller regression fix. renderOrchestrator.ts local executeRenderPipeline now hardcodes materializeSymlinks: false (previously shouldCopyExtractedFrames(process.platform), which was true on Windows and bypassed the link fallback entirely). the actual local Windows renderer does not request eager frame copies fakes process.platform = "win32" and verifies through executeRenderJob that the stage receives materializeSymlinks: false. That's the caller-path regression closed.

DISTRIBUTED isolation preserved. distributed materialization stays physically self-contained after cache removal passes materializeSymlinks: true explicitly, asserts the result is not a symlink, then rmSync(source, {recursive:true}) and reads a frame — bytes survive. The typecheck-green removal of the shouldCopyExtractedFrames export confirms no other caller is on the ambiguous per-platform toggle.

Junction removal preserves source frames. Real-Windows test creates the junction after the simulated symlink denial, writes updated bytes into the source, rmSync(outputDir, {recursive:true}), then reads the source file — updated bytes present. Node's rmSync({recursive:true}) on a reparse-point root unlinks the junction rather than traversing it, matching the "Tests on windows-latest: studio-engine-cli" CI run (none skipped).

Nit, non-blocking. EXDEV isn't in the junction capability-error whitelist — cross-volume extracted-cache vs compiled dir would surface as a hard error rather than degrading to copy. Rare in practice (both live under the render root), but a one-word add for anyone whose cache is on a different drive.

CI is fully green at head: Windows render verification (all lanes incl. real-junction studio-engine-cli), producer unit + integration, all 9 regression shards, typecheck, lint, format, CLI smoke, SDK contract.

— Review by tai (pr-review)

@jrusso1020
jrusso1020 merged commit b9aae16 into main Sep 7, 2026
55 checks passed
@jrusso1020
jrusso1020 deleted the fix/windows-frame-staging-links branch September 7, 2026 19:52
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.

2 participants