fix(plugin-cloud-storage): don't leave skipCloudStorage on a reused context - #17700
Open
luantaraschi wants to merge 1 commit into
Open
fix(plugin-cloud-storage): don't leave skipCloudStorage on a reused context#17700luantaraschi wants to merge 1 commit into
luantaraschi wants to merge 1 commit into
Conversation
…ontext The afterChange hook sets `skipCloudStorage` on `req.context`, then calls a nested `payload.update()`. That runs `createLocalReq`, which reassigns `req.context` to a fresh copy — so the `finally` cleared the flag off the copy and left it on the original object. When a caller passes one `context` object across several Local API creates, `createLocalReq` binds that same object to `req.context`, so the leftover flag makes every later upload return early. The documents are written with correct filenames and sizes, but no bytes reach storage and nothing is logged.
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.
Fixes #17546.
What
Passing one
contextobject across several Local APIcreate()calls on an upload collection uploads only the first file. Every later create succeeds, writes a fully-populated document (filename,mimeType,sizes,url), and puts nothing in storage — no error, no log line.@edrpls traced the mechanism precisely in the issue; this confirms it and fixes the last link.
The chain
createLocalReqassigns the caller'scontexttoreq.contextby reference when the fresh req has none —getRequestContextreturnscontextunchanged in that branch.req.context.skipCloudStorage = true, so it is now set on the caller's object.payload.update({ ..., req })runscreateLocalReqagain on that same req.req.contextis non-empty now, so line 139 reassignsreq.context = { ...req.context, ...context }— a new object.finally { delete req.context.skipCloudStorage }deletes it from that new object.create()binds it toreq.contextagain, the hook returns early at its first line, and no upload happens.Step 3 is the one that's easy to miss: the reassignment happens on the same
req, soreq.contextsilently stops pointing at what step 2 mutated.The fix
Capture the reference the flag is set on, and clear it from that:
The recursion guard still works — the nested
createLocalReqcopiesreq.contextincluding the flag, so the nested hook still sees it and returns early. Only the cleanup changes.I deliberately did not touch
getRequestContext. Handing the caller's object over by reference is what lets hooks write back into a caller's context, and changing that would be a much broader behavioural change than this bug warrants.Verified by running it
Added
uploads every file when one context object is reused across createstotest/plugin-cloud-storage/int.spec.ts. Three sequential creates sharing onecontext, thenHeadObjectagainst the bucket for every file and every generated size.Run against LocalStack + MongoDB in Docker:
Tests 1 passedafterChange.tsTests 1 failedThe control failure is the reported damage, not a proxy for it:
The first file (
image.png) verifies fine; the second one and its sizes are absent from the bucket while its document row exists. Reverting thefinallyline alone is enough to reproduce.Full suite after the change:
Test Files 2 passed · Tests 35 passed | 3 todo (38).Note on the assertion order
The test checks the bucket before asserting that
sharedContextis clean. I had it the other way round first, and the control then failed on the context assertion — technically correct, but it would have let a future regression report the internal symptom instead of the missing object. The bucket check is the one that describes what users lose.What I did not verify
I ran the
plugin-cloud-storagesuite only, on MongoDB with the S3 adapter against LocalStack. I did not run the otherstorage-*suites (azure, gcs, r2, vercel-blob) — the change is in the shared hook, so they exercise the same path, but I'm flagging it rather than implying I checked. Same for a real S3/R2 endpoint; the reporter covered R2.Checklist