Commit 3d7f705
fix(snapshots): Chunk image uploads to avoid fd exhaustion and 413 errors (#3249)
Uploading hundreds of images via `build snapshots` fails in two ways:
1. **Too many open files (EMFILE)**: All image file handles are opened
upfront and held until the batch send completes. This exceeds OS file
descriptor limits (~256 on macOS, ~1024 on Linux).
2. **413 Payload Too Large**: The objectstore client batches up to 1000
operations into a single HTTP request. With hundreds of images the
multipart body exceeds the server's size limit.
Both failures were confirmed with a real 753-image upload. 734 out of
753 images failed with 413 errors.
This PR splits `upload_images()` into two phases:
- **Phase 1 (pre-process)**: Iterate all images to detect filename
collisions, compute SHA-256 hashes, read sidecar metadata, and build
manifest entries — without opening any files for upload.
- **Phase 2 (chunked upload)**: Upload in batches of 100 images. For
each batch, open files, build a fresh `session.many()` builder, and
send. This bounds both open file descriptors and HTTP request payload
size.
Also includes minor code quality improvements: simplified scope
extraction, iterator-based collision formatting, and removal of
redundant bindings.
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>1 parent c7e4932 commit 3d7f705
4 files changed
Lines changed: 74 additions & 88 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
10 | 14 | | |
11 | 15 | | |
| 16 | + | |
12 | 17 | | |
13 | 18 | | |
14 | 19 | | |
| |||
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
44 | 44 | | |
45 | 45 | | |
46 | 46 | | |
47 | | - | |
| 47 | + | |
48 | 48 | | |
49 | 49 | | |
50 | 50 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
12 | | - | |
| 12 | + | |
13 | 13 | | |
14 | 14 | | |
15 | 15 | | |
| |||
303 | 303 | | |
304 | 304 | | |
305 | 305 | | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
306 | 311 | | |
307 | 312 | | |
308 | 313 | | |
| |||
318 | 323 | | |
319 | 324 | | |
320 | 325 | | |
321 | | - | |
| 326 | + | |
322 | 327 | | |
323 | | - | |
324 | | - | |
| 328 | + | |
325 | 329 | | |
326 | 330 | | |
327 | 331 | | |
328 | 332 | | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
329 | 344 | | |
330 | | - | |
331 | | - | |
332 | | - | |
333 | | - | |
334 | | - | |
335 | | - | |
336 | | - | |
337 | | - | |
| 345 | + | |
| 346 | + | |
338 | 347 | | |
339 | | - | |
340 | | - | |
341 | | - | |
342 | | - | |
343 | | - | |
344 | | - | |
345 | 348 | | |
346 | 349 | | |
347 | 350 | | |
| |||
350 | 353 | | |
351 | 354 | | |
352 | 355 | | |
353 | | - | |
354 | 356 | | |
355 | 357 | | |
356 | 358 | | |
| 359 | + | |
357 | 360 | | |
358 | 361 | | |
359 | 362 | | |
| |||
381 | 384 | | |
382 | 385 | | |
383 | 386 | | |
384 | | - | |
385 | | - | |
386 | | - | |
387 | | - | |
388 | | - | |
389 | | - | |
390 | 387 | | |
391 | | - | |
392 | | - | |
393 | | - | |
394 | | - | |
395 | | - | |
396 | | - | |
397 | | - | |
398 | | - | |
399 | 388 | | |
400 | 389 | | |
401 | 390 | | |
| |||
404 | 393 | | |
405 | 394 | | |
406 | 395 | | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
407 | 400 | | |
408 | 401 | | |
409 | 402 | | |
410 | 403 | | |
411 | 404 | | |
412 | 405 | | |
413 | 406 | | |
414 | | - | |
415 | | - | |
416 | | - | |
417 | | - | |
418 | | - | |
419 | | - | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
420 | 417 | | |
421 | 418 | | |
422 | 419 | | |
423 | | - | |
| 420 | + | |
424 | 421 | | |
425 | | - | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
426 | 431 | | |
427 | | - | |
428 | | - | |
429 | | - | |
430 | | - | |
431 | | - | |
432 | | - | |
433 | | - | |
434 | | - | |
435 | | - | |
436 | | - | |
437 | | - | |
438 | | - | |
439 | | - | |
440 | | - | |
441 | | - | |
442 | | - | |
443 | | - | |
444 | | - | |
445 | | - | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
446 | 440 | | |
| 441 | + | |
447 | 442 | | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
| 447 | + | |
| 448 | + | |
| 449 | + | |
| 450 | + | |
448 | 451 | | |
449 | 452 | | |
450 | 453 | | |
| |||
0 commit comments