Skip to content

[Repo Assist] perf: replace blocking fs.writeFileSync/readFileSync with async I/O in format()#110

Draft
github-actions[bot] wants to merge 1 commit intomasterfrom
repo-assist/perf-async-file-io-2026-03-27-6651bbafda7e2f73
Draft

[Repo Assist] perf: replace blocking fs.writeFileSync/readFileSync with async I/O in format()#110
github-actions[bot] wants to merge 1 commit intomasterfrom
repo-assist/perf-async-file-io-2026-03-27-6651bbafda7e2f73

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

🤖 This is an automated draft PR from Repo Assist, an AI assistant.

Summary

Replaces the two synchronous file-I/O calls in format() with async equivalents, freeing the VS Code extension host thread while PHP source files are being written to / read from the OS temp directory.

Root cause

format() used fs.writeFileSync to write the document's text to a temp file before spawning phpcbf, and fs.readFileSync to read the fixed text back on exit codes 1 or 2. Both calls block the entire extension host JavaScript thread. For large PHP files (or on slow storage such as a network drive or a Docker container) this manifests as a perceptible UI freeze.

Changes

Before After
fs.writeFileSync(fileName, text) (sync, blocking) fs.writeFile(fileName, text, cb) (async, non-blocking)
fs.readFileSync(fileName, "utf-8") (sync, blocking) fs.readFile(fileName, "utf-8", cb) (async, non-blocking)

The entire format() body is now wrapped in the Promise executor so the spawn and all event-handler setup happen inside the writeFile callback, once the temp file is ready.

Incidental fixes

  • phpcbfError / deferred stdout-listener dead code removed: The original code set phpcbfError = true inside the exit callback, then checked the flag synchronously after constructing the Promise — by which point the flag was always false. The stdout listener for exit code 3 was therefore never attached. Replaced with a direct window.showErrorMessage call in the exit handler.
  • Tidied up: const in place of let where applicable; removed a stale // console.log(code) comment.

Trade-offs

  • The async restructuring adds one level of callback nesting. Acceptable given Node.js conventions for file I/O.
  • Behaviour is otherwise identical to before for all exit codes (0, 1, 2, 3, default).

Test Status

Check Result
npm run test:unit (7 findFiles unit tests) ✅ All pass

(The integration test suite requires a full VS Code environment and cannot run in CI for this project.)

Closes: N/A (performance improvement, no associated issue)

Generated by Repo Assist ·

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/repo-assist.md@346204513ecfa08b81566450d7d599556807389f

…n format()

Synchronous file operations in the extension host block VS Code's entire
JavaScript thread while writing/reading PHP source files to/from the OS
temp directory. For large PHP files this causes a visible pause in the UI.

Changes:
- fs.writeFileSync → fs.writeFile (async): temp file is written inside the
  Promise executor, so the extension host thread is freed immediately after
  spawning the write.
- fs.readFileSync → fs.readFile (async): fixed-file read on exit codes 1/2
  is now async; unlink is called inside the readFile callback so the temp
  file is cleaned up after the async read completes.
- Removed the phpcbfError flag + deferred stdout-listener pattern, which
  was effectively dead code (the synchronous if-check always saw false). Code
  3 now calls window.showErrorMessage directly in the exit handler, matching
  the documented intent.
- Removed leftover 'console.log(code)' comment in close handler.

All 7 unit tests pass (npm run test:unit).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants