fix(storage-gcs): destroy the GCS read stream when the response body is cancelled#16959
Open
via-marketing-co-il wants to merge 1 commit into
Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
What?
getFilein@payloadcms/storage-gcswraps the GCS Node read stream in a webReadableStreamwith nocancel()handler and unguardedcontroller.enqueue/close/errorcalls.Why?
When the consumer cancels the response body — a browser aborting an image/video download mid-stream, or server code that serves HEAD by reading GET and cancelling the body — the controller closes but the GCS stream keeps emitting. The next
'data'event then throws an uncaught exception at process level (it originates inside an EventEmitter listener, so no promise chain catches it), and the GCS download keeps running (wasted egress):Reproduced in production on Cloud Run (Payload 3.84.1, also verified present in 3.85.1 and current
main): a singlecurl -I https://<host>/api/media/file/<file>.webp-style cancelled read triggers it deterministically ~50–100 ms after the response headers are returned.Notably,
@payloadcms/storage-s3already handles this case (abort listener + stream destroy, #13430);storage-gcsnever received the equivalent.How?
Mirror the S3 adapter's intent with the minimal change inside the existing
ReadableStreamwrapper:cancel()handler that destroys the GCS read stream (stops the download, prevents further events)enqueue/close/errorbehind asettledflagenqueueever throws anyway, destroy the stream instead of crashing the processNo behavior change for normal, fully-consumed reads (ranged or full). Fixes the uncaught
ERR_INVALID_STATEcrash-noise and the leaked GCS download on every cancelled media response.