Use streaming responses to prevent memory allocation errors for large files #3043
+106
−30
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.
Modified PHPRequestHandler to use php.runStream() instead of php.run() to avoid buffering large responses in memory. This prevents "Array buffer allocation failed" errors when downloading files larger than 2GB.
Updated all related components to support both PHPResponse and StreamedPHPResponse return types, ensuring backward compatibility for smaller responses while enabling efficient streaming for large file downloads.
Motivation for the change, related issues
STU-73
Related to Automattic/studio#1058
When downloading large files (>2GB) through WordPress Playground, the system attempted to buffer the entire response in memory, causing "Array buffer allocation failed" errors. This occurred because
PHPRequestHandlerused the deprecatedphp.run()method which buffers responses. By switching tophp.runStream(), responses now stream directly to the client without requiring large memory allocations, enabling downloads of files up to several gigabytes in size.Implementation details
The core change is in
PHPRequestHandler.request(), which now callsphp.runStream()instead of the deprecatedphp.run()method. This returns aStreamedPHPResponsecontaining ReadableStreams for headers, stdout, and stderr, rather than buffering the entire response in memory.All methods in the request chain were updated to return
Promise<PHPResponse | StreamedPHPResponse>to support both buffered and streamed responses. This maintains backward compatibility for small responses while enabling streaming for large files.In
start-server.ts, the HTTP handler now detectsStreamedPHPResponseinstances and streams the stdout directly to the HTTP response using a ReadableStream reader, avoiding memory allocation. Buffered responses continue to work as before.Other components like
export-wxr.tswere updated to handle both response types by checkinginstanceof StreamedPHPResponseand accessingstdoutBytesfor streamed responses orbytesfor buffered ones.Testing Instructions (or ideally a Blueprint)
TBD