Stream multipart UploadPart on Workers (avoid buffering parts in WASM memory)
Los mantenedores suelen responder en 1 día
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Aptitud para principiantes
- 68/100
Línea de trabajo
Lee crates/cf-workers/src/backend.rs, comparando send_raw con la plantilla de forward, y luego sigue execute_multipart y la rama NeedsBody en crates/core/src/proxy.rs. Sigue S3RequestSigner para el presign de los parámetros de consulta; se considera terminado cuando UploadPart se transmite a través de Forward sin almacenamiento en búfer del cuerpo de WASM ni cálculo del hash del payload, mientras las demás operaciones multipart conservan el comportamiento indicado.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Problem
Multipart UploadPart flows through the NeedsBody → send_raw path, which buffers the entire part body in WASM linear memory on the Cloudflare Workers runtime:
collect_js_bodycopies the request stream JS→WASM (array_buffer()+to_vec())execute_multipartcomputes SHA256 over the whole part for the outbound signature (hash_payload)send_rawcopies WASM→JS (js_sys::Uint8Array::from) to hand tofetch
So each part incurs two full body copies across the JS/WASM boundary + an O(N) SHA256, and is held in the worker's 128 MB memory heap. Single-object PutObject does not have this problem — it uses the zero-copy forward() path (the ReadableStream is handed straight to fetch, signed with UNSIGNED-PAYLOAD so no hashing).
For typical part sizes (~8 MiB) this is a few ms of CPU and fine. But the 128 MB memory limit caps the maximum multipart_chunksize a client can use before the worker OOMs.
Proposed fix
Route UploadPart through the streaming forward() path instead of send_raw:
- Generate a presigned URL for
PUT /{key}?partNumber=N&uploadId=X.object_store'sSigner::signed_urlonly takes aPath(no query params), so presign manually viaS3RequestSigner— it already builds SigV4 canonical query strings (incl. value-less params, fixed in #88). - Return
HandlerAction::Forwardso theReadableStreamstreams straight throughfetch: no WASM buffering, no payload hash.
CompleteMultipartUpload stays on send_raw (its small XML body must be signed/forwarded), but that body is tiny. CreateMultipartUpload/AbortMultipartUpload are body-less and could also move to the forward path opportunistically.
Interaction with Cloudflare's request-body size limit
Even with streaming, every request through a Worker is bounded by the plan's request-body limit (100 MB Free/Pro, 200 MB Business, 500 MB Enterprise default). Streaming changes which limit binds:
- Today (buffered): a part is capped by the smaller of the 128 MB memory limit and the plan body limit.
- After streaming: a part is capped only by the plan body limit (no WASM buffering).
So streaming lets clients use the full plan body limit for part sizes. It does not lift the body limit itself — that's a hard platform constraint (see separate doc note). Large objects must still be uploaded as multipart with part sizes ≤ the plan limit.
Impact
- Removes the 128 MB part-size ceiling on Workers (raises it to the plan body limit).
- Eliminates 2 body copies + 1 SHA256 per part → lower CPU.
- Brings
UploadPartto parity with the zero-copyPutObjectpath.
References
crates/cf-workers/src/backend.rs—send_raw(buffers);forwardis the zero-copy templatecrates/core/src/proxy.rs—execute_multipart,dispatch_operation(theNeedsBodyarm)- Deferred from #88 to keep that PR scoped to correctness.
- Lenguaje dominante
- Rust
- Estrellas
- 20
- Forks
- 1
- Merge medio
- 1 d 8 h
- PR fusionados (30 d)
- 10
Preparar el entorno
- Incluye un Dockerfile o un archivo de Docker Compose
- Sin plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de developmentseed/multistore
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 74/100
developmentseed/multistore#160 ·
Los mantenedores suelen responder en 1 día
-
List of a prefix 503s when a single object key contains an empty path segment (//)Posiblemente ocupada @alukach la tomó hace 97 días. Abierto
Dificultad 3/5 1-2 días Aptitud para principiantes 55/100
developmentseed/multistore#116 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
oidc-provider: optional `oidc_session_name` backend-option to override RoleSessionName derivationAbierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 35/100
developmentseed/multistore#84 ·
Los mantenedores suelen responder en 1 día
-
Credential cache key (role ARN) doesn't capture the full minted identity (subject + extra_claims)Abierto
Dificultad 4/5 3-5 días Aptitud para principiantes 55/100
developmentseed/multistore#81 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 3/5 1-2 días Aptitud para principiantes 65/100
developmentseed/multistore#70 ·
Los mantenedores suelen responder en 1 día
Todos los issues de developmentseed/multistore
Issues similares
-
A-UI C-Bug S-Needs-Triage
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100
bevyengine/bevy#26330 ·
Los mantenedores suelen responder en 2 días
-
Update releases hashes in READMEAbierto
Dificultad 1/5 Menos de una hora Aptitud para principiantes 72/100
chipsalliance/caliptra-sw#4335 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 84/100
aaif-goose/goose#13158 ·
Los mantenedores suelen responder en 1 día
-
agent enhancement provider:anthropic providers triaged
Dificultad 2/5 1-3 horas Aptitud para principiantes 66/100
can1357/oh-my-pi#17148 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
`invalid_regex` example is wrongAbiertoA-documentation good first issue
Dificultad 1/5 Menos de una hora Aptitud para principiantes 82/100
rust-lang/rust-clippy#17926 · 1 comentario ·
Los mantenedores suelen responder en 1 día