( videoId: string, )
| 535 | } |
| 536 | |
| 537 | async function waitForEditCompletion( |
| 538 | videoId: string, |
| 539 | ): Promise<VideoEditRenderResult> { |
| 540 | let lastStatus = "processing"; |
| 541 | |
| 542 | for ( |
| 543 | let attempt = 0; |
| 544 | attempt < MEDIA_SERVER_COMPLETION_MAX_ATTEMPTS; |
| 545 | attempt++ |
| 546 | ) { |
| 547 | await waitForRetry(MEDIA_SERVER_COMPLETION_POLL_INTERVAL_MS); |
| 548 | |
| 549 | const [upload] = await db() |
| 550 | .select({ |
| 551 | phase: videoUploads.phase, |
| 552 | processingProgress: videoUploads.processingProgress, |
| 553 | processingMessage: videoUploads.processingMessage, |
| 554 | processingError: videoUploads.processingError, |
| 555 | }) |
| 556 | .from(videoUploads) |
| 557 | .where(eq(videoUploads.videoId, videoId as Video.VideoId)); |
| 558 | |
| 559 | if (!upload) { |
| 560 | throw new Error("Edit processing state disappeared"); |
| 561 | } |
| 562 | |
| 563 | if (upload.phase === "complete") { |
| 564 | const metadata = await getCompletedMetadata(videoId); |
| 565 | if (!metadata) { |
| 566 | throw new Error("Edit completed but video metadata is missing"); |
| 567 | } |
| 568 | |
| 569 | return { metadata }; |
| 570 | } |
| 571 | |
| 572 | if (upload.processingError) { |
| 573 | throw new Error(upload.processingError); |
| 574 | } |
| 575 | |
| 576 | if (upload.phase === "error") { |
| 577 | throw new Error(upload.processingMessage || "Video edit failed"); |
| 578 | } |
| 579 | |
| 580 | lastStatus = [ |
| 581 | upload.phase, |
| 582 | typeof upload.processingProgress === "number" |
| 583 | ? `${upload.processingProgress}%` |
| 584 | : null, |
| 585 | upload.processingMessage, |
| 586 | ] |
| 587 | .filter(Boolean) |
| 588 | .join(" "); |
| 589 | } |
| 590 | |
| 591 | throw new Error(`Video edit timed out while ${lastStatus}`); |
| 592 | } |
| 593 | |
| 594 | function getEditInvalidationCallerReference( |
no test coverage detected