Skip to content

fix(studio): keep file-change subscription stable across redraws - #3855

Closed
hassnalalshaikh wants to merge 1 commit into
heygen-com:mainfrom
hassnalalshaikh:codex/stable-editor-file-subscription
Closed

hassnalalshaikh wants to merge 1 commit into
heygen-com:mainfrom
hassnalalshaikh:codex/stable-editor-file-subscription

Conversation

@hassnalalshaikh

@hassnalalshaikh hassnalalshaikh commented Sep 10, 2026 •

Copy link
Copy Markdown

What

Keep Studio's file-change subscription stable across unrelated screen updates.

Why

Studio currently reconnects its file-change subscription whenever its parent redraws. useEditorSave returns a fresh getPendingCandidate closure; this propagates through useFileManager into useExternalFileChangeCoordinator and changes the callback that owns the subscription effect. Playback and render-progress updates therefore close and recreate /api/events even when the project and file have not changed.

How

Keep the getter stable with useCallback, reading the existing ref at call time. This preserves current pending-edit behavior while avoiding unnecessary subscription replacement.

Test plan

  • Regression test verifies a stable getter across 30 redraws, the latest pending source, and discard behavior.
  • Both save and external-file-change suites pass: 18 tests.
  • Related workspace builds, including Studio's production build and declarations, pass.
  • Changed files pass oxlint and oxfmt.
  • Manual browser retest of the production Studio build: a real 20-second, six-scene composition played to completion; Export advanced through 600 frames and completed in 49 seconds; Download emitted its browser event; a text edit saved through Studio and remained after a full page reload. The output probes as 20 seconds, 1080 x 1920, H.264 with AAC audio. This was a local Node server, not a deployed proxy test.

A separate local integration probe using both original hooks and the existing subscription test adapter reproduces 31 subscriptions and 30 cleanups across 30 redraws before the fix, and one retained subscription with the fix. This establishes the React subscription regression; it does not claim to fix an independent proxy's connection cleanup or every export-progress failure. No documentation change is required for this internal bug fix.

@hassnalalshaikh
hassnalalshaikh marked this pull request as ready for review September 10, 2026 19:34
@jrusso1020

Copy link
Copy Markdown
Collaborator

Reviewed at 0981093c. This looks fixed on main already, so I'd close it. When you opened it, the /api/events subscription effect depended on processChange, so a new getPendingCandidate closure on each render rebuilt that chain and reconnected. #4889 (merged 2026-10-03) changed the subscription to call processChangeRef.current with an empty dependency list, and #5126 did the same for drainOnePending. On main the subscription is created once per mount, however often getPendingCandidate changes identity.

The useCallback would still be a little tidier, but it no longer fixes a reconnect. The new test also checks getter identity rather than the subscription, so it wouldn't catch the real bug coming back. Thanks for the careful write-up.

Need: no, #4889 fixed it · Size: ok · Reuse: n/a · Simpler: n/a

— Rames

@jrusso1020 jrusso1020 closed this Oct 24, 2026
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