( s3: S3Client, uris: string[], workDir: string, format: DistributedFormat, )
| 443 | } |
| 444 | |
| 445 | async function downloadChunkObjects( |
| 446 | s3: S3Client, |
| 447 | uris: string[], |
| 448 | workDir: string, |
| 449 | format: DistributedFormat, |
| 450 | ): Promise<string[]> { |
| 451 | const chunksDir = join(workDir, "chunks"); |
| 452 | mkdirSync(chunksDir, { recursive: true }); |
| 453 | // Each chunk is an independent S3 GET (+ untar for png-sequence). Run |
| 454 | // them in parallel — assemble's wall-clock is otherwise dominated by |
| 455 | // `Σ chunk-download-ms` instead of `max(chunk-download-ms)`. Preserve |
| 456 | // the input order by writing into a pre-sized array rather than |
| 457 | // pushing as each task settles. |
| 458 | const local: string[] = new Array<string>(uris.length); |
| 459 | await Promise.all( |
| 460 | uris.map(async (uri, i) => { |
| 461 | if (!uri) { |
| 462 | throw new Error(`[handler] chunk URI at index ${i} is empty`); |
| 463 | } |
| 464 | const { key } = parseS3Uri(uri); |
| 465 | const localPath = join(chunksDir, basename(key)); |
| 466 | await downloadS3ObjectToFile(s3, uri, localPath); |
| 467 | if (format === "png-sequence") { |
| 468 | const dirPath = join(chunksDir, `frames-${pad(i)}`); |
| 469 | await untarDirectory(localPath, dirPath); |
| 470 | local[i] = dirPath; |
| 471 | } else { |
| 472 | local[i] = localPath; |
| 473 | } |
| 474 | }), |
| 475 | ); |
| 476 | return local; |
| 477 | } |
| 478 | |
| 479 | // ── Helpers ───────────────────────────────────────────────────────────────── |
| 480 |
no test coverage detected