Use streaming responses to prevent memory allocation errors for large files#3043
Conversation
… files 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.
68eca49 to
d5702cb
Compare
|
@epeicher This seems like a pretty good idea! It seems like holding on to |
Thanks for the input @adamziel! I was initially trying to minimize changes while I evaluated whether this approach was the right direction. Your suggestion makes sense though, and I agree it will simplify things. I will apply it and continue working on it, since the current approach works in Studio but not in Playground. |
|
From the linked task:
That's exactly right @adamziel, the ai1wm plugin creates a temporary archive locally, and that is the limitation I am currently facing while working on this. The streaming approach suggested as part of this PR has worked for the playground CLI with Studio, but it totally breaks the Playground application. I would need to identify an approach that only uses streaming under very specific and controlled circumstances. Maybe using |
|
@adamziel I have tried a similar but slightly different approach as part of #3222 that might supersede this PR. In the new one, I added a new I have tested #3222 in both Studio and Playground and have not found any regressions. In Studio, exporting a site larger than 2GB works now. |
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