@skyphusion-labs/vivijure-core 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +661 -0
- package/README.md +87 -0
- package/dist/audio-routing.d.ts +2 -0
- package/dist/audio-routing.d.ts.map +1 -0
- package/dist/audio-routing.js +4 -0
- package/dist/audio-routing.js.map +1 -0
- package/dist/audio-stage.d.ts +4 -0
- package/dist/audio-stage.d.ts.map +1 -0
- package/dist/audio-stage.js +25 -0
- package/dist/audio-stage.js.map +1 -0
- package/dist/beat-analyze.d.ts +22 -0
- package/dist/beat-analyze.d.ts.map +1 -0
- package/dist/beat-analyze.js +111 -0
- package/dist/beat-analyze.js.map +1 -0
- package/dist/beat-sync-types.d.ts +33 -0
- package/dist/beat-sync-types.d.ts.map +1 -0
- package/dist/beat-sync-types.js +4 -0
- package/dist/beat-sync-types.js.map +1 -0
- package/dist/bundle-assembler.d.ts +54 -0
- package/dist/bundle-assembler.d.ts.map +1 -0
- package/dist/bundle-assembler.js +376 -0
- package/dist/bundle-assembler.js.map +1 -0
- package/dist/bundle-durations.d.ts +5 -0
- package/dist/bundle-durations.d.ts.map +1 -0
- package/dist/bundle-durations.js +68 -0
- package/dist/bundle-durations.js.map +1 -0
- package/dist/bundle-storyboard.d.ts +11 -0
- package/dist/bundle-storyboard.d.ts.map +1 -0
- package/dist/bundle-storyboard.js +82 -0
- package/dist/bundle-storyboard.js.map +1 -0
- package/dist/captions.d.ts +25 -0
- package/dist/captions.d.ts.map +1 -0
- package/dist/captions.js +56 -0
- package/dist/captions.js.map +1 -0
- package/dist/cast-db.d.ts +61 -0
- package/dist/cast-db.d.ts.map +1 -0
- package/dist/cast-db.js +324 -0
- package/dist/cast-db.js.map +1 -0
- package/dist/cast-lora-train.d.ts +18 -0
- package/dist/cast-lora-train.d.ts.map +1 -0
- package/dist/cast-lora-train.js +215 -0
- package/dist/cast-lora-train.js.map +1 -0
- package/dist/cast-loras.d.ts +21 -0
- package/dist/cast-loras.d.ts.map +1 -0
- package/dist/cast-loras.js +69 -0
- package/dist/cast-loras.js.map +1 -0
- package/dist/clip-content-validate.d.ts +43 -0
- package/dist/clip-content-validate.d.ts.map +1 -0
- package/dist/clip-content-validate.js +115 -0
- package/dist/clip-content-validate.js.map +1 -0
- package/dist/clip-job-model.d.ts +42 -0
- package/dist/clip-job-model.d.ts.map +1 -0
- package/dist/clip-job-model.js +8 -0
- package/dist/clip-job-model.js.map +1 -0
- package/dist/clip-validate.d.ts +33 -0
- package/dist/clip-validate.d.ts.map +1 -0
- package/dist/clip-validate.js +247 -0
- package/dist/clip-validate.js.map +1 -0
- package/dist/d1-retry.d.ts +20 -0
- package/dist/d1-retry.d.ts.map +1 -0
- package/dist/d1-retry.js +67 -0
- package/dist/d1-retry.js.map +1 -0
- package/dist/db-env.d.ts +6 -0
- package/dist/db-env.d.ts.map +1 -0
- package/dist/db-env.js +2 -0
- package/dist/db-env.js.map +1 -0
- package/dist/dialogue-lines.d.ts +23 -0
- package/dist/dialogue-lines.d.ts.map +1 -0
- package/dist/dialogue-lines.js +84 -0
- package/dist/dialogue-lines.js.map +1 -0
- package/dist/film-advance-lease.d.ts +9 -0
- package/dist/film-advance-lease.d.ts.map +1 -0
- package/dist/film-advance-lease.js +19 -0
- package/dist/film-advance-lease.js.map +1 -0
- package/dist/film-model.d.ts +415 -0
- package/dist/film-model.d.ts.map +1 -0
- package/dist/film-model.js +541 -0
- package/dist/film-model.js.map +1 -0
- package/dist/film-orchestrator.d.ts +216 -0
- package/dist/film-orchestrator.d.ts.map +1 -0
- package/dist/film-orchestrator.js +2204 -0
- package/dist/film-orchestrator.js.map +1 -0
- package/dist/film-render-bridge.d.ts +26 -0
- package/dist/film-render-bridge.d.ts.map +1 -0
- package/dist/film-render-bridge.js +176 -0
- package/dist/film-render-bridge.js.map +1 -0
- package/dist/finish-hash.d.ts +10 -0
- package/dist/finish-hash.d.ts.map +1 -0
- package/dist/finish-hash.js +60 -0
- package/dist/finish-hash.js.map +1 -0
- package/dist/index.d.ts +48 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +45 -0
- package/dist/index.js.map +1 -0
- package/dist/key-safety.d.ts +5 -0
- package/dist/key-safety.d.ts.map +1 -0
- package/dist/key-safety.js +23 -0
- package/dist/key-safety.js.map +1 -0
- package/dist/lora-bundle.d.ts +19 -0
- package/dist/lora-bundle.d.ts.map +1 -0
- package/dist/lora-bundle.js +75 -0
- package/dist/lora-bundle.js.map +1 -0
- package/dist/lora-keys.d.ts +2 -0
- package/dist/lora-keys.d.ts.map +1 -0
- package/dist/lora-keys.js +4 -0
- package/dist/lora-keys.js.map +1 -0
- package/dist/modules/conformance.d.ts +58 -0
- package/dist/modules/conformance.d.ts.map +1 -0
- package/dist/modules/conformance.js +369 -0
- package/dist/modules/conformance.js.map +1 -0
- package/dist/modules/manifest-validate.d.ts +5 -0
- package/dist/modules/manifest-validate.d.ts.map +1 -0
- package/dist/modules/manifest-validate.js +60 -0
- package/dist/modules/manifest-validate.js.map +1 -0
- package/dist/modules/registry.d.ts +184 -0
- package/dist/modules/registry.d.ts.map +1 -0
- package/dist/modules/registry.js +653 -0
- package/dist/modules/registry.js.map +1 -0
- package/dist/modules/render-pipeline.d.ts +38 -0
- package/dist/modules/render-pipeline.d.ts.map +1 -0
- package/dist/modules/render-pipeline.js +40 -0
- package/dist/modules/render-pipeline.js.map +1 -0
- package/dist/modules/types.d.ts +544 -0
- package/dist/modules/types.d.ts.map +1 -0
- package/dist/modules/types.js +57 -0
- package/dist/modules/types.js.map +1 -0
- package/dist/operator-config.d.ts +20 -0
- package/dist/operator-config.d.ts.map +1 -0
- package/dist/operator-config.js +85 -0
- package/dist/operator-config.js.map +1 -0
- package/dist/output-extract.d.ts +8 -0
- package/dist/output-extract.d.ts.map +1 -0
- package/dist/output-extract.js +129 -0
- package/dist/output-extract.js.map +1 -0
- package/dist/planner-prompt.d.ts +12 -0
- package/dist/planner-prompt.d.ts.map +1 -0
- package/dist/planner-prompt.js +337 -0
- package/dist/planner-prompt.js.map +1 -0
- package/dist/planner-yaml.d.ts +15 -0
- package/dist/planner-yaml.d.ts.map +1 -0
- package/dist/planner-yaml.js +157 -0
- package/dist/planner-yaml.js.map +1 -0
- package/dist/platform/fetcher.d.ts +3 -0
- package/dist/platform/fetcher.d.ts.map +1 -0
- package/dist/platform/fetcher.js +7 -0
- package/dist/platform/fetcher.js.map +1 -0
- package/dist/platform/index.d.ts +6 -0
- package/dist/platform/index.d.ts.map +1 -0
- package/dist/platform/index.js +5 -0
- package/dist/platform/index.js.map +1 -0
- package/dist/platform/object-store-r2.d.ts +26 -0
- package/dist/platform/object-store-r2.d.ts.map +1 -0
- package/dist/platform/object-store-r2.js +74 -0
- package/dist/platform/object-store-r2.js.map +1 -0
- package/dist/platform/orchestrator-context.d.ts +20 -0
- package/dist/platform/orchestrator-context.d.ts.map +1 -0
- package/dist/platform/orchestrator-context.js +28 -0
- package/dist/platform/orchestrator-context.js.map +1 -0
- package/dist/platform/r2-types.d.ts +41 -0
- package/dist/platform/r2-types.d.ts.map +1 -0
- package/dist/platform/r2-types.js +3 -0
- package/dist/platform/r2-types.js.map +1 -0
- package/dist/platform/types.d.ts +90 -0
- package/dist/platform/types.d.ts.map +1 -0
- package/dist/platform/types.js +23 -0
- package/dist/platform/types.js.map +1 -0
- package/dist/preflight.d.ts +57 -0
- package/dist/preflight.d.ts.map +1 -0
- package/dist/preflight.js +243 -0
- package/dist/preflight.js.map +1 -0
- package/dist/presign.d.ts +5 -0
- package/dist/presign.d.ts.map +1 -0
- package/dist/presign.js +24 -0
- package/dist/presign.js.map +1 -0
- package/dist/public-id.d.ts +8 -0
- package/dist/public-id.d.ts.map +1 -0
- package/dist/public-id.js +25 -0
- package/dist/public-id.js.map +1 -0
- package/dist/render-adopt.d.ts +3 -0
- package/dist/render-adopt.d.ts.map +1 -0
- package/dist/render-adopt.js +92 -0
- package/dist/render-adopt.js.map +1 -0
- package/dist/render-log.d.ts +25 -0
- package/dist/render-log.d.ts.map +1 -0
- package/dist/render-log.js +139 -0
- package/dist/render-log.js.map +1 -0
- package/dist/render-module-config.d.ts +28 -0
- package/dist/render-module-config.d.ts.map +1 -0
- package/dist/render-module-config.js +124 -0
- package/dist/render-module-config.js.map +1 -0
- package/dist/render-mux.d.ts +18 -0
- package/dist/render-mux.d.ts.map +1 -0
- package/dist/render-mux.js +69 -0
- package/dist/render-mux.js.map +1 -0
- package/dist/render-orchestrator.d.ts +71 -0
- package/dist/render-orchestrator.d.ts.map +1 -0
- package/dist/render-orchestrator.js +376 -0
- package/dist/render-orchestrator.js.map +1 -0
- package/dist/render-sweep.d.ts +5 -0
- package/dist/render-sweep.d.ts.map +1 -0
- package/dist/render-sweep.js +62 -0
- package/dist/render-sweep.js.map +1 -0
- package/dist/renders-db.d.ts +129 -0
- package/dist/renders-db.d.ts.map +1 -0
- package/dist/renders-db.js +752 -0
- package/dist/renders-db.js.map +1 -0
- package/dist/runpod-submit.d.ts +151 -0
- package/dist/runpod-submit.d.ts.map +1 -0
- package/dist/runpod-submit.js +469 -0
- package/dist/runpod-submit.js.map +1 -0
- package/dist/runpod-types.d.ts +2 -0
- package/dist/runpod-types.d.ts.map +1 -0
- package/dist/runpod-types.js +4 -0
- package/dist/runpod-types.js.map +1 -0
- package/dist/scatter-notify.d.ts +4 -0
- package/dist/scatter-notify.d.ts.map +1 -0
- package/dist/scatter-notify.js +43 -0
- package/dist/scatter-notify.js.map +1 -0
- package/dist/scatter-orchestrator-types.d.ts +56 -0
- package/dist/scatter-orchestrator-types.d.ts.map +1 -0
- package/dist/scatter-orchestrator-types.js +3 -0
- package/dist/scatter-orchestrator-types.js.map +1 -0
- package/dist/scatter-orchestrator.d.ts +70 -0
- package/dist/scatter-orchestrator.d.ts.map +1 -0
- package/dist/scatter-orchestrator.js +614 -0
- package/dist/scatter-orchestrator.js.map +1 -0
- package/dist/scatter.d.ts +35 -0
- package/dist/scatter.d.ts.map +1 -0
- package/dist/scatter.js +171 -0
- package/dist/scatter.js.map +1 -0
- package/dist/secret-store.d.ts +5 -0
- package/dist/secret-store.d.ts.map +1 -0
- package/dist/secret-store.js +19 -0
- package/dist/secret-store.js.map +1 -0
- package/dist/shot-durations-parse.d.ts +3 -0
- package/dist/shot-durations-parse.d.ts.map +1 -0
- package/dist/shot-durations-parse.js +43 -0
- package/dist/shot-durations-parse.js.map +1 -0
- package/dist/srt.d.ts +11 -0
- package/dist/srt.d.ts.map +1 -0
- package/dist/srt.js +54 -0
- package/dist/srt.js.map +1 -0
- package/dist/storyboard-ids.d.ts +2 -0
- package/dist/storyboard-ids.d.ts.map +1 -0
- package/dist/storyboard-ids.js +12 -0
- package/dist/storyboard-ids.js.map +1 -0
- package/dist/storyboard-projects-db.d.ts +31 -0
- package/dist/storyboard-projects-db.d.ts.map +1 -0
- package/dist/storyboard-projects-db.js +153 -0
- package/dist/storyboard-projects-db.js.map +1 -0
- package/dist/storyboard-validate.d.ts +72 -0
- package/dist/storyboard-validate.d.ts.map +1 -0
- package/dist/storyboard-validate.js +595 -0
- package/dist/storyboard-validate.js.map +1 -0
- package/dist/structured-events.d.ts +6 -0
- package/dist/structured-events.d.ts.map +1 -0
- package/dist/structured-events.js +15 -0
- package/dist/structured-events.js.map +1 -0
- package/dist/tar.d.ts +9 -0
- package/dist/tar.d.ts.map +1 -0
- package/dist/tar.js +151 -0
- package/dist/tar.js.map +1 -0
- package/dist/voices.d.ts +12 -0
- package/dist/voices.d.ts.map +1 -0
- package/dist/voices.js +37 -0
- package/dist/voices.js.map +1 -0
- package/package.json +71 -0
|
@@ -0,0 +1,614 @@
|
|
|
1
|
+
// Scatter/gather render orchestrator: N parallel film jobs (clips_only shards) + one gather assemble.
|
|
2
|
+
import { advanceFilmJob, callVideoFinish, cancelFilmJob, classifyAssembleTransport, clipKeysFromFilmJob, filmJobDocKey, filmPhaseToShardStatus, orderFinalClips, startFilmJob, runFilmFinish, resolveClipDurationFloor, mapClipDurationsToShots, resolvePlannedSeconds, findClipDurationShortfalls, } from "./film-orchestrator.js";
|
|
3
|
+
import { readShotDurationsFromBundle } from "./bundle-durations.js";
|
|
4
|
+
import { filmJobToPollView, filterScenesByShotIds, orderScenesByShotIds, mapRenderOverridesToModuleConfigs } from "./film-render-bridge.js";
|
|
5
|
+
import { presignR2Get, presignR2Put } from "./presign.js";
|
|
6
|
+
import { resolveStagedAudioKey } from "./audio-stage.js";
|
|
7
|
+
import { defaultGpuDoorModule, discoverModules, servingForHook } from "./modules/registry.js";
|
|
8
|
+
import { readBundleScenes } from "./bundle-storyboard.js";
|
|
9
|
+
import { getProjectById } from "./storyboard-projects-db.js";
|
|
10
|
+
import { buildDialogueLines } from "./dialogue-lines.js";
|
|
11
|
+
import { gatherDecision, isScatterParentJobId, scatterParentJobId, scatterShards, } from "./scatter.js";
|
|
12
|
+
import { claimFinish, getFinishState, getRenderIdByJobId, insertRender, buildInsertRenderStmt, markFinishDone, markFinishFailed, markRenderFailedByJobId, updateRenderFromView, } from "./renders-db.js";
|
|
13
|
+
import { resolveCastLoras, untrainedCastMessage } from "./cast-loras.js";
|
|
14
|
+
import { fireNotifyForScatter } from "./scatter-notify.js";
|
|
15
|
+
import { isTransientD1Error, withD1Retry, d1ErrorCode } from "./d1-retry.js";
|
|
16
|
+
export { isScatterParentJobId as isScatterJobId };
|
|
17
|
+
const MAX_ASSEMBLE_ATTEMPTS = 6;
|
|
18
|
+
const scatterDocKey = (id) => `renders/${id}/scatter-job.json`;
|
|
19
|
+
const scatterOutKey = (id) => `renders/${id}/film.mp4`;
|
|
20
|
+
async function loadScatterJob(env, scatterId) {
|
|
21
|
+
const obj = await env.R2_RENDERS.get(scatterDocKey(scatterId));
|
|
22
|
+
if (!obj)
|
|
23
|
+
return null;
|
|
24
|
+
return JSON.parse(await obj.text());
|
|
25
|
+
}
|
|
26
|
+
async function saveScatterJob(env, job) {
|
|
27
|
+
await env.R2_RENDERS.put(scatterDocKey(job.scatter_id), JSON.stringify(job), {
|
|
28
|
+
httpMetadata: { contentType: "application/json" },
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
async function loadFilmJobDoc(env, filmId) {
|
|
32
|
+
const obj = await env.R2_RENDERS.get(filmJobDocKey(filmId));
|
|
33
|
+
if (!obj)
|
|
34
|
+
return null;
|
|
35
|
+
return JSON.parse(await obj.text());
|
|
36
|
+
}
|
|
37
|
+
/** Read the stored storyboard (D1 last_storyboard) and build the per-shot dialogue batch (authored
|
|
38
|
+
* line + cast-resolved voice). Returns [] when there's no project_id, no stored storyboard, or no
|
|
39
|
+
* dialogue -- a silent film. The bundle can't carry this (lossy), so D1 is the source of truth. */
|
|
40
|
+
async function resolveDialogueLines(env, args, voices, shotIds) {
|
|
41
|
+
if (args.project_id == null)
|
|
42
|
+
return [];
|
|
43
|
+
const project = await getProjectById(env, args.project_id);
|
|
44
|
+
if (!project?.last_storyboard)
|
|
45
|
+
return [];
|
|
46
|
+
return buildDialogueLines(project.last_storyboard, voices, shotIds);
|
|
47
|
+
}
|
|
48
|
+
export async function startScatterRender(env, args) {
|
|
49
|
+
const modules = await discoverModules(env);
|
|
50
|
+
if (servingForHook(modules, "keyframe").length === 0) {
|
|
51
|
+
throw new Error("no keyframe module installed (bind MODULE_KEYFRAME)");
|
|
52
|
+
}
|
|
53
|
+
if (servingForHook(modules, "motion.backend").length === 0) {
|
|
54
|
+
throw new Error("no motion.backend module installed");
|
|
55
|
+
}
|
|
56
|
+
const { pretrained, voices, castIds, skipped, skippedDetail } = await resolveCastLoras(env, args.cast_loras);
|
|
57
|
+
// #739: castLoras is OPTIONAL on scatter. Absent/empty -> shards render generic, exactly like the
|
|
58
|
+
// film/render siblings. The old "castLoras required for scatter" was unintended coupling baked in at
|
|
59
|
+
// the v0.2.0 bulk ship (no rationale anywhere, and nothing downstream needs a non-empty cast). A
|
|
60
|
+
// PRESENT-but-not-ready binding is STILL rejected (the #738-symmetric untrained-cast message), so the
|
|
61
|
+
// relax never reopens the silent-drop class -- the hScatter door turns this into a 400 before any spend.
|
|
62
|
+
if (skipped.length) {
|
|
63
|
+
throw new Error(untrainedCastMessage(skippedDetail));
|
|
64
|
+
}
|
|
65
|
+
const parsed = await readBundleScenes(env, args.bundle_key);
|
|
66
|
+
const scenes = parsed.map((s) => ({
|
|
67
|
+
shot_id: s.shot_id,
|
|
68
|
+
prompt: s.prompt,
|
|
69
|
+
seconds: s.seconds,
|
|
70
|
+
}));
|
|
71
|
+
const expected = args.shot_ids.filter((s) => typeof s === "string" && s.length > 0);
|
|
72
|
+
if (expected.length < 2)
|
|
73
|
+
throw new Error("scatter requires >= 2 shots");
|
|
74
|
+
// Talking characters: the dialogue is dropped by the lossy bundle, so read the AUTHORITATIVE
|
|
75
|
+
// storyboard from D1 (last_storyboard) and resolve each speaking shot's voice from the cast (voices,
|
|
76
|
+
// off the same rows resolveCastLoras already read). Absent project_id / no dialogue -> a silent film.
|
|
77
|
+
const dialogueLines = await resolveDialogueLines(env, args, voices, expected);
|
|
78
|
+
const shards = scatterShards({
|
|
79
|
+
shotIds: expected,
|
|
80
|
+
shardCount: args.shard_count,
|
|
81
|
+
pretrainedLoras: pretrained,
|
|
82
|
+
});
|
|
83
|
+
if (shards.length < 2)
|
|
84
|
+
throw new Error("scatter requires >= 2 shards");
|
|
85
|
+
const mapped = mapRenderOverridesToModuleConfigs(args.render_overrides, args.quality_tier, modules);
|
|
86
|
+
const motionBackend = args.motion_backend ?? mapped.motion_backend ?? defaultGpuDoorModule(modules)?.name;
|
|
87
|
+
if (!motionBackend)
|
|
88
|
+
throw new Error('no gpu-door motion.backend module (ui.locality "byo"/"local") is installed');
|
|
89
|
+
const scatterId = scatterParentJobId(crypto.randomUUID());
|
|
90
|
+
const stagedAudio = await resolveStagedAudioKey(env, args.audio_key);
|
|
91
|
+
const scatterJob = {
|
|
92
|
+
scatter_id: scatterId,
|
|
93
|
+
project: args.project,
|
|
94
|
+
bundle_key: args.bundle_key,
|
|
95
|
+
quality_tier: args.quality_tier,
|
|
96
|
+
expected_shot_ids: expected,
|
|
97
|
+
shard_film_ids: [],
|
|
98
|
+
shard_shots: shards.map((s) => s.shots),
|
|
99
|
+
motion_backend: motionBackend,
|
|
100
|
+
audio_key: stagedAudio,
|
|
101
|
+
has_dialogue: dialogueLines.length > 0,
|
|
102
|
+
scenes,
|
|
103
|
+
dialogue_lines: dialogueLines,
|
|
104
|
+
film_titles: args.film_titles,
|
|
105
|
+
film_finish_config: mapped.film_finish_config,
|
|
106
|
+
project_id: args.project_id ?? null,
|
|
107
|
+
render_overrides: args.render_overrides,
|
|
108
|
+
phase: "shards",
|
|
109
|
+
created_at: Date.now(),
|
|
110
|
+
};
|
|
111
|
+
// RUNNABILITY-FIRST (#289): build the shard FILM jobs (their docs live in R2), collecting the
|
|
112
|
+
// render-row specs to persist to D1 afterwards. The D1 rows are a UI-list PROJECTION, not what
|
|
113
|
+
// makes the render runnable -- so we never write them before the runnable R2 state.
|
|
114
|
+
const shardRows = [];
|
|
115
|
+
for (const shard of shards) {
|
|
116
|
+
const shardScenes = filterScenesByShotIds(scenes, shard.shots);
|
|
117
|
+
// Each shard runs its own finish chain (incl. lip-sync), so it carries only its shots' dialogue.
|
|
118
|
+
const shardShotSet = new Set(shard.shots);
|
|
119
|
+
const shardDialogue = dialogueLines.filter((l) => shardShotSet.has(l.shot_id));
|
|
120
|
+
const film = await startFilmJob(env, {
|
|
121
|
+
project: args.project,
|
|
122
|
+
bundle_key: args.bundle_key,
|
|
123
|
+
scenes: shardScenes,
|
|
124
|
+
motion_backend: motionBackend,
|
|
125
|
+
keyframe_backend: mapped.keyframe_backend,
|
|
126
|
+
keyframe_config: mapped.keyframe_config,
|
|
127
|
+
motion_config: mapped.motion_config,
|
|
128
|
+
finish_config: mapped.finish_config,
|
|
129
|
+
speech_config: mapped.speech_config,
|
|
130
|
+
master_config: mapped.master_config,
|
|
131
|
+
clips_only: true,
|
|
132
|
+
pretrained_loras: shard.pretrainedLoras,
|
|
133
|
+
cast_loras: castIds,
|
|
134
|
+
dialogue_lines: shardDialogue,
|
|
135
|
+
});
|
|
136
|
+
scatterJob.shard_film_ids.push(film.film_id);
|
|
137
|
+
shardRows.push({ jobId: film.film_id, status: filmJobToPollView(film, null).status });
|
|
138
|
+
}
|
|
139
|
+
await finalizeScatterSubmit(env, scatterJob, shardRows);
|
|
140
|
+
return scatterJob;
|
|
141
|
+
}
|
|
142
|
+
/** Persist a scatter submit so it can NEVER orphan a render (#289).
|
|
143
|
+
*
|
|
144
|
+
* The runnable R2 doc is written FIRST: the poll/advance path runs entirely off it
|
|
145
|
+
* (loadScatterJob), so once it lands the render is runnable and a later transient cannot strand
|
|
146
|
+
* it. The D1 render rows are a UI-list projection, written AFTER, best-effort: the parent (so the
|
|
147
|
+
* shards can FK it), then the shard rows as one all-or-nothing env.DB.batch, each wrapped in
|
|
148
|
+
* withD1Retry. A persistent D1 failure is logged as a structured d1.error and SWALLOWED -- the
|
|
149
|
+
* submit still succeeds (render is runnable) and the missing rows self-heal on the first poll
|
|
150
|
+
* (ensureScatterRenderRow). This is the cure for the orphan-row 422: a mid-submit blip can no
|
|
151
|
+
* longer leave a row with no job, nor fail the whole submit. The submit spans two stores (D1 rows
|
|
152
|
+
* + R2 docs), so a single DB.batch cannot make it truly atomic; runnability-first ordering plus
|
|
153
|
+
* self-heal makes the residual gap benign. */
|
|
154
|
+
export async function finalizeScatterSubmit(env, scatterJob, shardRows) {
|
|
155
|
+
await saveScatterJob(env, scatterJob); // <- render is RUNNABLE from here
|
|
156
|
+
try {
|
|
157
|
+
await withD1Retry(() => insertRender(env, {
|
|
158
|
+
jobId: scatterJob.scatter_id,
|
|
159
|
+
project: scatterJob.project,
|
|
160
|
+
bundleKey: scatterJob.bundle_key,
|
|
161
|
+
qualityTier: scatterJob.quality_tier,
|
|
162
|
+
renderOverrides: scatterJob.render_overrides,
|
|
163
|
+
status: "IN_QUEUE",
|
|
164
|
+
mode: "full",
|
|
165
|
+
projectId: scatterJob.project_id ?? null,
|
|
166
|
+
}), { label: "scatter.submit.parent" });
|
|
167
|
+
const parentId = await getRenderIdByJobId(env, scatterJob.scatter_id);
|
|
168
|
+
if (shardRows.length) {
|
|
169
|
+
const stmts = shardRows.map((r) => buildInsertRenderStmt(env, {
|
|
170
|
+
jobId: r.jobId,
|
|
171
|
+
project: scatterJob.project,
|
|
172
|
+
bundleKey: scatterJob.bundle_key,
|
|
173
|
+
qualityTier: scatterJob.quality_tier,
|
|
174
|
+
renderOverrides: scatterJob.render_overrides,
|
|
175
|
+
status: r.status,
|
|
176
|
+
mode: "full",
|
|
177
|
+
projectId: scatterJob.project_id ?? null,
|
|
178
|
+
parentId: parentId ?? undefined,
|
|
179
|
+
}));
|
|
180
|
+
await withD1Retry(() => env.DB.batch(stmts), { label: "scatter.submit.shards" });
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
catch (e) {
|
|
184
|
+
// Render is already runnable off the R2 doc; the rows self-heal on first poll. Log, don't throw.
|
|
185
|
+
console.log(JSON.stringify({
|
|
186
|
+
ev: "d1.error", op: "scatter.submit.rows", scatter_id: scatterJob.scatter_id, code: d1ErrorCode(e),
|
|
187
|
+
}));
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
async function muxScatterAudio(env, job) {
|
|
191
|
+
const silentKey = job.silent_film_key;
|
|
192
|
+
const audioKey = job.audio_key;
|
|
193
|
+
if (!silentKey || !audioKey) {
|
|
194
|
+
job.film_key = silentKey;
|
|
195
|
+
job.phase = "done";
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
if (!env.VIDEO_FINISH_VPC) {
|
|
199
|
+
job.phase = "failed";
|
|
200
|
+
job.error = "video-finish VPC binding not configured";
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
const outKey = job.mux_output_key ?? scatterOutKey(job.scatter_id);
|
|
204
|
+
job.mux_output_key = outKey;
|
|
205
|
+
const resp = await callVideoFinish(env, {
|
|
206
|
+
clips: [{ url: await presignR2Get(env, silentKey, 1800) }],
|
|
207
|
+
outputUrl: await presignR2Put(env, outKey, 1800),
|
|
208
|
+
outputKey: outKey,
|
|
209
|
+
audioUrl: await presignR2Get(env, audioKey, 1800),
|
|
210
|
+
remuxAudioOnly: true,
|
|
211
|
+
});
|
|
212
|
+
if (!resp || !resp.ok) {
|
|
213
|
+
job.phase = "failed";
|
|
214
|
+
job.error = `scatter audio mux failed: HTTP ${resp?.status ?? "?"}`;
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
let body;
|
|
218
|
+
try {
|
|
219
|
+
body = (await resp.json());
|
|
220
|
+
}
|
|
221
|
+
catch {
|
|
222
|
+
job.phase = "failed";
|
|
223
|
+
job.error = "scatter mux returned non-JSON";
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
if (!body.ok) {
|
|
227
|
+
job.phase = "failed";
|
|
228
|
+
job.error = `scatter mux failed: ${body.error || "unknown"}`;
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
job.film_key = outKey;
|
|
232
|
+
job.phase = "done";
|
|
233
|
+
}
|
|
234
|
+
async function maybeFinalizeScatter(env, job) {
|
|
235
|
+
if (job.phase !== "done" || !job.film_key)
|
|
236
|
+
return;
|
|
237
|
+
const st = await getFinishState(env, job.scatter_id);
|
|
238
|
+
if (st?.finish_state === "done")
|
|
239
|
+
return;
|
|
240
|
+
await runScatterFilmFinish(env, job);
|
|
241
|
+
await finalizeScatterDone(env, job);
|
|
242
|
+
}
|
|
243
|
+
/** Run the film.finish chain (subtitle / title / credit cards) on the assembled+muxed scatter film,
|
|
244
|
+
* mirroring the single-film path's inline film.finish (#284/#285). The assembled clip order ==
|
|
245
|
+
* expected_shot_ids order (orderFinalClips), so the FULL scenes + dialogue_lines give correctly aligned
|
|
246
|
+
* cumulative captions. FAIL-SAFE + idempotent: guarded by job.film_finish so a re-driven finalize never
|
|
247
|
+
* double-runs, and runFilmFinish soft-degrades (a card miss never drops the assembled film). */
|
|
248
|
+
async function runScatterFilmFinish(env, job) {
|
|
249
|
+
if (job.film_finish || !job.film_key)
|
|
250
|
+
return; // already run (or nothing to card)
|
|
251
|
+
job.film_finish_dispatched ??= {};
|
|
252
|
+
job.film_finish_polls ??= {};
|
|
253
|
+
job.film_finish_attempts ??= {};
|
|
254
|
+
job.film_finish_prepend ??= {};
|
|
255
|
+
const r = await runFilmFinish(env, {
|
|
256
|
+
film_key: job.film_key,
|
|
257
|
+
// Caption scenes in the SAME order the gather assembles the clips (expected_shot_ids), NOT bundle
|
|
258
|
+
// order, so buildCaptionCues' cumulative timeline matches the cut (the crux, #284/#285).
|
|
259
|
+
scenes: orderScenesByShotIds(job.scenes ?? [], job.expected_shot_ids),
|
|
260
|
+
dialogue_lines: job.dialogue_lines,
|
|
261
|
+
film_titles: job.film_titles,
|
|
262
|
+
film_finish_config: job.film_finish_config,
|
|
263
|
+
bundle_key: job.bundle_key,
|
|
264
|
+
project: job.project,
|
|
265
|
+
job_id: job.scatter_id,
|
|
266
|
+
actual_durations: job.actual_clip_durations,
|
|
267
|
+
}, undefined, {
|
|
268
|
+
// #600 in-flight guard: persist a dispatch BEFORE it fires so a killed tick cannot re-dispatch a
|
|
269
|
+
// duplicate encode of the same step.
|
|
270
|
+
dispatched: job.film_finish_dispatched,
|
|
271
|
+
persistDispatch: async (key, ts) => { job.film_finish_dispatched[key] = ts; await saveScatterJob(env, job); },
|
|
272
|
+
// #602 async job+poll: persist the per-step module poll token + terminal-failure count so a long
|
|
273
|
+
// single film.finish step survives across gather ticks instead of re-burning each tick.
|
|
274
|
+
polls: job.film_finish_polls,
|
|
275
|
+
attempts: job.film_finish_attempts,
|
|
276
|
+
persistPoll: async (key, token) => {
|
|
277
|
+
if (token === null)
|
|
278
|
+
delete job.film_finish_polls[key];
|
|
279
|
+
else
|
|
280
|
+
job.film_finish_polls[key] = token;
|
|
281
|
+
await saveScatterJob(env, job);
|
|
282
|
+
},
|
|
283
|
+
// #663: persist title-card prepend offsets across gather ticks so the post-chain .srt re-time recovers
|
|
284
|
+
// them even when the prepending step is adopted (not re-folded) on a later tick.
|
|
285
|
+
prepends: job.film_finish_prepend,
|
|
286
|
+
persistPrepend: async (key, seconds) => { job.film_finish_prepend[key] = seconds; await saveScatterJob(env, job); },
|
|
287
|
+
});
|
|
288
|
+
if (!r.ran) {
|
|
289
|
+
job.film_finish = { applied: [], errors: [] };
|
|
290
|
+
return;
|
|
291
|
+
} // no film.finish module -> mark + skip
|
|
292
|
+
if (r.errors.length > 0)
|
|
293
|
+
console.warn(`scatter film.finish errors for ${job.scatter_id}: ${r.errors.join("; ")}`);
|
|
294
|
+
if (r.degraded)
|
|
295
|
+
console.warn(`scatter film.finish degraded for ${job.scatter_id}: ${r.degraded} -- film shipped WITHOUT cards`);
|
|
296
|
+
if (!r.complete) {
|
|
297
|
+
await saveScatterJob(env, job);
|
|
298
|
+
return;
|
|
299
|
+
} // #600 in-flight: leave film_finish UNSET so the next gather tick resumes; dispatched map already persisted
|
|
300
|
+
job.film_finish = { applied: r.applied, adopted: r.adopted, errors: r.errors, steps: r.steps, degraded: r.degraded, sidecar_key: r.sidecar_key };
|
|
301
|
+
job.film_key = r.film_key;
|
|
302
|
+
await saveScatterJob(env, job); // persist carded key + outcome before finalize records it
|
|
303
|
+
}
|
|
304
|
+
async function assembleScatterClips(env, job, clips) {
|
|
305
|
+
if (!env.VIDEO_FINISH_VPC) {
|
|
306
|
+
job.phase = "failed";
|
|
307
|
+
job.error = "video-finish VPC binding not configured";
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
const presigned = [];
|
|
311
|
+
for (const c of clips) {
|
|
312
|
+
presigned.push({ url: await presignR2Get(env, c.clip_key, 1800) });
|
|
313
|
+
}
|
|
314
|
+
const outputKey = scatterOutKey(job.scatter_id);
|
|
315
|
+
// Talking film: the shards' lip-sync baked per-shot audio into each clip, so preserve it through the
|
|
316
|
+
// concat (the container then silent-pads any audio-less clip to a uniform track). Without this the
|
|
317
|
+
// gather strips ALL clip audio (-an) and the film comes out silent -- mirrors film-orchestrator's
|
|
318
|
+
// single-film assemble (keepClipAudio on dialogue). Also keeps the audio of the clips that DID
|
|
319
|
+
// lip-sync even when a sibling clip didn't, so one short finish chain can't silence the whole film.
|
|
320
|
+
const resp = await callVideoFinish(env, {
|
|
321
|
+
clips: presigned,
|
|
322
|
+
outputUrl: await presignR2Put(env, outputKey, 1800),
|
|
323
|
+
outputKey,
|
|
324
|
+
keepClipAudio: !!job.has_dialogue,
|
|
325
|
+
});
|
|
326
|
+
const transport = classifyAssembleTransport(resp ? resp.status : null, job.assemble_attempts ?? 0, MAX_ASSEMBLE_ATTEMPTS);
|
|
327
|
+
job.assemble_attempts = transport.attempts;
|
|
328
|
+
if (transport.state === "retry") {
|
|
329
|
+
job.phase = "gather";
|
|
330
|
+
job.error = transport.error;
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
if (transport.state === "exhausted") {
|
|
334
|
+
job.phase = "failed";
|
|
335
|
+
job.error = transport.error;
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
if (!resp || !resp.ok) {
|
|
339
|
+
job.phase = "failed";
|
|
340
|
+
job.error = `video-finish gather returned ${resp?.status ?? "?"}`;
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
let body;
|
|
344
|
+
try {
|
|
345
|
+
body = (await resp.json());
|
|
346
|
+
}
|
|
347
|
+
catch {
|
|
348
|
+
job.phase = "failed";
|
|
349
|
+
job.error = "video-finish gather returned non-JSON";
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
if (!body.ok) {
|
|
353
|
+
job.phase = "failed";
|
|
354
|
+
job.error = `video-finish gather failed: ${body.error || "unknown"}`;
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
// #697/#698: capture the ACTUAL per-clip assembled seconds (submit order == gather clips order) and
|
|
358
|
+
// gate each shot against its plan, the same per-shot honesty gate as the single-film assemble. The
|
|
359
|
+
// film-level ratio check below still catches a gross whole-film drop; this catches ONE truncated shot
|
|
360
|
+
// the total would mask. Persisted so the gather film.finish chain times captions to the real cut (#698).
|
|
361
|
+
const actual = mapClipDurationsToShots(clips, body.clipDurations);
|
|
362
|
+
job.actual_clip_durations = Object.keys(actual).length > 0 ? actual : undefined;
|
|
363
|
+
if (Object.keys(actual).length > 0) {
|
|
364
|
+
const bundleDurations = await readShotDurationsFromBundle(env, job.bundle_key);
|
|
365
|
+
const planned = resolvePlannedSeconds(job.scenes ?? [], bundleDurations);
|
|
366
|
+
const fraction = resolveClipDurationFloor(typeof env.FILM_CLIP_DURATION_FLOOR === "string" ? env.FILM_CLIP_DURATION_FLOOR : undefined);
|
|
367
|
+
const shortfalls = findClipDurationShortfalls(clips, actual, planned, fraction);
|
|
368
|
+
if (shortfalls.length > 0) {
|
|
369
|
+
job.phase = "failed";
|
|
370
|
+
job.error = `duration gate: ${shortfalls.length} shot(s) delivered below ${Math.round(fraction * 100)}% of plan: ` +
|
|
371
|
+
shortfalls.map((sf) => `${sf.shot_id} ${sf.actual.toFixed(2)}s vs planned ${sf.planned.toFixed(2)}s (floor ${sf.floor.toFixed(2)}s)`).join("; ");
|
|
372
|
+
console.warn(`scatter ${job.scatter_id}: ${job.error}`);
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
// Fail loud: a scatter render must NEVER silently complete a PARTIAL film. If the assembled film
|
|
377
|
+
// is materially shorter than the sum of the cut shots' durations, clips were dropped in the
|
|
378
|
+
// assemble (a fetch miss or a concat truncation) -- error instead of shipping a 1-of-N film. This
|
|
379
|
+
// closes the gap that let a 3-shot render COMPLETE with one shot; per-shot clips stay intact in R2
|
|
380
|
+
// for a re-driven assemble. The 0.5 ratio catches a gross partial (v4 shipped 36%) while tolerating
|
|
381
|
+
// legitimate per-clip tail/beat-trim (music films) without false alarms; the container-side guard
|
|
382
|
+
// (output vs its actual normalized inputs) is the precise, false-positive-free backstop.
|
|
383
|
+
const expectedSeconds = (job.scenes ?? [])
|
|
384
|
+
.filter((s) => job.expected_shot_ids.includes(s.shot_id))
|
|
385
|
+
.reduce((sum, s) => sum + (Number.isFinite(s.seconds) && s.seconds > 0 ? s.seconds : 0), 0);
|
|
386
|
+
const assembledSeconds = typeof body.durationSeconds === "number" ? body.durationSeconds : 0;
|
|
387
|
+
// [#287] instrumentation: clips we SENT vs the container received vs concatenated duration --
|
|
388
|
+
// definitively locates a 3 -> 1 drop (worker-sent-fewer vs container-side) on the next run.
|
|
389
|
+
console.log(JSON.stringify({
|
|
390
|
+
ev: "scatter.assemble.result", scatter_id: job.scatter_id, sent: clips.length,
|
|
391
|
+
clipsReceived: body.clipsReceived, shots: body.shots, durationSeconds: body.durationSeconds,
|
|
392
|
+
expectedSeconds,
|
|
393
|
+
}));
|
|
394
|
+
if (expectedSeconds > 0 && assembledSeconds > 0 && assembledSeconds < expectedSeconds * 0.5) {
|
|
395
|
+
job.phase = "failed";
|
|
396
|
+
job.error = `assemble dropped clips: ${assembledSeconds.toFixed(1)}s assembled vs ~${expectedSeconds.toFixed(1)}s expected across ${job.expected_shot_ids.length} shots`;
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
job.silent_film_key = outputKey;
|
|
400
|
+
if (job.audio_key) {
|
|
401
|
+
job.phase = "mux";
|
|
402
|
+
await muxScatterAudio(env, job);
|
|
403
|
+
}
|
|
404
|
+
else {
|
|
405
|
+
job.film_key = outputKey;
|
|
406
|
+
job.phase = "done";
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
async function finalizeScatterDone(env, job) {
|
|
410
|
+
if (!job.film_key)
|
|
411
|
+
return;
|
|
412
|
+
await markFinishDone(env, job.scatter_id, job.film_key, JSON.stringify({
|
|
413
|
+
output_key: job.film_key,
|
|
414
|
+
project: job.project,
|
|
415
|
+
mode: "full",
|
|
416
|
+
}));
|
|
417
|
+
await fireNotifyForScatter(env, job);
|
|
418
|
+
}
|
|
419
|
+
async function advanceScatterGather(env, job) {
|
|
420
|
+
const st = await getFinishState(env, job.scatter_id);
|
|
421
|
+
const claimed = await claimFinish(env, job.scatter_id);
|
|
422
|
+
if (!claimed && st?.finish_state !== "finishing")
|
|
423
|
+
return;
|
|
424
|
+
const clipMap = new Map();
|
|
425
|
+
for (const filmId of job.shard_film_ids) {
|
|
426
|
+
const fj = await loadFilmJobDoc(env, filmId);
|
|
427
|
+
if (!fj || fj.phase !== "done")
|
|
428
|
+
continue;
|
|
429
|
+
for (const [shotId, key] of (await clipKeysFromFilmJob(env, fj)).entries()) {
|
|
430
|
+
clipMap.set(shotId, key);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
const clips = orderFinalClips(job.expected_shot_ids.map((shot_id) => ({ shot_id, prompt: "", seconds: 4 })), [...clipMap.entries()].map(([shot_id, clip_key]) => ({ shot_id, clip_key })));
|
|
434
|
+
// [#287] instrumentation: pin where 3 -> 1 happens. Logs shots_expected vs clips_gathered (and
|
|
435
|
+
// the resolved shot ids) at the assemble decision; the container result is logged below.
|
|
436
|
+
console.log(JSON.stringify({
|
|
437
|
+
ev: "scatter.gather.assemble", scatter_id: job.scatter_id,
|
|
438
|
+
shots_expected: job.expected_shot_ids.length, clips_gathered: clips.length,
|
|
439
|
+
shot_ids: clips.map((c) => c.shot_id),
|
|
440
|
+
}));
|
|
441
|
+
if (clips.length !== job.expected_shot_ids.length) {
|
|
442
|
+
const err = "gather: missing clips after finish decision";
|
|
443
|
+
await markFinishFailed(env, job.scatter_id, err);
|
|
444
|
+
job.phase = "failed";
|
|
445
|
+
job.error = err;
|
|
446
|
+
return;
|
|
447
|
+
}
|
|
448
|
+
await assembleScatterClips(env, job, clips);
|
|
449
|
+
if (job.phase === "failed") {
|
|
450
|
+
await markFinishFailed(env, job.scatter_id, job.error || "scatter gather failed");
|
|
451
|
+
}
|
|
452
|
+
else {
|
|
453
|
+
await maybeFinalizeScatter(env, job);
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
/** Map a shard's advance outcome to its gather status. The key distinction (watchdog defense-in-
|
|
457
|
+
* depth): an `errored` shard is UNDETERMINED -> IN_PROGRESS (recoverable; the gather keeps waiting
|
|
458
|
+
* and retries), NOT a SHARD_DEAD status -- so a transient-D1-blocked shard is never declared
|
|
459
|
+
* "owning shard dead". Only a genuinely-failed phase or a vanished doc maps to FAILED. */
|
|
460
|
+
export function shardStatusForOutcome(outcome) {
|
|
461
|
+
if (outcome.ok)
|
|
462
|
+
return filmPhaseToShardStatus(outcome.job);
|
|
463
|
+
return outcome.reason === "doc_missing" ? "FAILED" : "IN_PROGRESS";
|
|
464
|
+
}
|
|
465
|
+
/** Self-heal the D1 render row from the runnable R2 doc (#289). Cheap read first -- a no-op once
|
|
466
|
+
* the row exists (the normal path). Only when the row is MISSING (a submit whose best-effort D1
|
|
467
|
+
* write lost the flaky window) does it insert the row at the doc's current status and, when
|
|
468
|
+
* terminal, fill status/output via updateRenderFromView. Never aborts the advance: a transient is
|
|
469
|
+
* left for the next poll; a non-transient is logged. */
|
|
470
|
+
export async function ensureScatterRenderRow(env, job, ctx) {
|
|
471
|
+
try {
|
|
472
|
+
if ((await getRenderIdByJobId(env, job.scatter_id)) != null)
|
|
473
|
+
return;
|
|
474
|
+
const view = scatterJobToPollView(job);
|
|
475
|
+
await insertRender(env, {
|
|
476
|
+
jobId: job.scatter_id,
|
|
477
|
+
project: job.project,
|
|
478
|
+
bundleKey: job.bundle_key,
|
|
479
|
+
qualityTier: job.quality_tier,
|
|
480
|
+
renderOverrides: job.render_overrides,
|
|
481
|
+
status: view.status,
|
|
482
|
+
mode: "full",
|
|
483
|
+
projectId: job.project_id ?? null,
|
|
484
|
+
});
|
|
485
|
+
if (view.status !== "IN_PROGRESS")
|
|
486
|
+
await updateRenderFromView(env, view, ctx);
|
|
487
|
+
console.log(JSON.stringify({ ev: "scatter.selfheal.row", scatter_id: job.scatter_id, status: view.status }));
|
|
488
|
+
}
|
|
489
|
+
catch (e) {
|
|
490
|
+
if (!isTransientD1Error(e)) {
|
|
491
|
+
console.log(JSON.stringify({ ev: "d1.error", op: "scatter.selfheal.row", scatter_id: job.scatter_id, code: d1ErrorCode(e) }));
|
|
492
|
+
}
|
|
493
|
+
// never abort the advance for a projection-row write; a transient retries on the next poll.
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
export async function advanceScatterJob(env, scatterId, ctx) {
|
|
497
|
+
const job = await loadScatterJob(env, scatterId);
|
|
498
|
+
if (!job)
|
|
499
|
+
return null;
|
|
500
|
+
// #289 self-heal: the submit writes the R2 doc before the D1 rows, so a mid-submit blip can
|
|
501
|
+
// leave a runnable render whose UI-list row never got written. Insert it if missing (cheap read
|
|
502
|
+
// first; no-op once it exists) so the render shows up and its terminal status/output get logged.
|
|
503
|
+
await ensureScatterRenderRow(env, job, ctx);
|
|
504
|
+
if (job.cancelled)
|
|
505
|
+
return scatterJobToPollView(job);
|
|
506
|
+
if (job.phase === "done" || job.phase === "failed")
|
|
507
|
+
return scatterJobToPollView(job);
|
|
508
|
+
const shardStatuses = [];
|
|
509
|
+
const present = new Set();
|
|
510
|
+
for (let i = 0; i < job.shard_film_ids.length; i++) {
|
|
511
|
+
const filmId = job.shard_film_ids[i];
|
|
512
|
+
const shots = job.shard_shots[i] ?? [];
|
|
513
|
+
// Per-shard isolation (defense-in-depth, pairs with withD1Retry #229): a shard whose advance
|
|
514
|
+
// ERRORS this tick (a transient D1/R2 blip outliving the in-tick retries, or any mid-advance
|
|
515
|
+
// throw) is UNDETERMINED, not dead -- the catch keeps it IN_PROGRESS so the gather waits and
|
|
516
|
+
// retries next tick instead of declaring its shots "owning shard dead", and one shard's error
|
|
517
|
+
// no longer aborts the others' advance. Genuinely-dead still fails fast: a `failed` film phase
|
|
518
|
+
// or a vanished film-job doc (null) both map to FAILED. A permanently-stuck shard is still
|
|
519
|
+
// backstopped by the film job's own hard-deadline (it eventually reports phase=failed).
|
|
520
|
+
let status;
|
|
521
|
+
try {
|
|
522
|
+
const r = await advanceFilmJob(env, filmId);
|
|
523
|
+
if (r) {
|
|
524
|
+
await updateRenderFromView(env, filmJobToPollView(r.job, r.clipJob), ctx);
|
|
525
|
+
status = shardStatusForOutcome({ ok: true, job: r.job });
|
|
526
|
+
if (r.job.phase === "done") {
|
|
527
|
+
for (const [shotId] of (await clipKeysFromFilmJob(env, r.job)).entries()) {
|
|
528
|
+
present.add(shotId);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
else {
|
|
533
|
+
status = shardStatusForOutcome({ ok: false, reason: "doc_missing" });
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
catch (e) {
|
|
537
|
+
const kind = isTransientD1Error(e) ? "transient D1" : "advance error";
|
|
538
|
+
console.warn(`scatter ${scatterId} shard ${filmId} undetermined (${kind}); treating as in-progress, will retry: ${e.message}`);
|
|
539
|
+
status = shardStatusForOutcome({ ok: false, reason: "errored" });
|
|
540
|
+
}
|
|
541
|
+
shardStatuses.push({ status, shots });
|
|
542
|
+
}
|
|
543
|
+
if (job.phase === "shards") {
|
|
544
|
+
const decision = gatherDecision([...present], job.expected_shot_ids, shardStatuses);
|
|
545
|
+
if (decision.kind === "failed") {
|
|
546
|
+
job.phase = "failed";
|
|
547
|
+
job.error = decision.reason;
|
|
548
|
+
await markRenderFailedByJobId(env, scatterId, decision.reason);
|
|
549
|
+
}
|
|
550
|
+
else if (decision.kind === "finish") {
|
|
551
|
+
job.phase = "gather";
|
|
552
|
+
await advanceScatterGather(env, job);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
if (job.phase === "gather") {
|
|
556
|
+
await advanceScatterGather(env, job);
|
|
557
|
+
}
|
|
558
|
+
if (job.phase === "mux") {
|
|
559
|
+
await muxScatterAudio(env, job);
|
|
560
|
+
await maybeFinalizeScatter(env, job);
|
|
561
|
+
}
|
|
562
|
+
await saveScatterJob(env, job);
|
|
563
|
+
const view = scatterJobToPollView(job);
|
|
564
|
+
if (view.status !== "IN_PROGRESS")
|
|
565
|
+
await updateRenderFromView(env, view, ctx);
|
|
566
|
+
return view;
|
|
567
|
+
}
|
|
568
|
+
export function scatterJobToPollView(job) {
|
|
569
|
+
let status;
|
|
570
|
+
let output;
|
|
571
|
+
if (job.cancelled) {
|
|
572
|
+
status = "CANCELLED";
|
|
573
|
+
}
|
|
574
|
+
else if (job.phase === "done") {
|
|
575
|
+
status = "COMPLETED";
|
|
576
|
+
output = { output_key: job.film_key, project: job.project, mode: "full" };
|
|
577
|
+
}
|
|
578
|
+
else if (job.phase === "failed") {
|
|
579
|
+
status = "FAILED";
|
|
580
|
+
}
|
|
581
|
+
else {
|
|
582
|
+
status = "IN_PROGRESS";
|
|
583
|
+
output = {
|
|
584
|
+
phase: job.phase,
|
|
585
|
+
project: job.project,
|
|
586
|
+
shards: job.shard_film_ids.length,
|
|
587
|
+
scene_total: job.expected_shot_ids.length,
|
|
588
|
+
};
|
|
589
|
+
}
|
|
590
|
+
return {
|
|
591
|
+
jobId: job.scatter_id,
|
|
592
|
+
status,
|
|
593
|
+
statusRaw: job.phase,
|
|
594
|
+
output,
|
|
595
|
+
error: job.error,
|
|
596
|
+
executionTimeMs: Math.max(0, Date.now() - job.created_at),
|
|
597
|
+
};
|
|
598
|
+
}
|
|
599
|
+
export async function cancelScatterJob(env, scatterId) {
|
|
600
|
+
const job = await loadScatterJob(env, scatterId);
|
|
601
|
+
if (!job)
|
|
602
|
+
return null;
|
|
603
|
+
if (job.phase === "done" || job.phase === "failed")
|
|
604
|
+
return scatterJobToPollView(job);
|
|
605
|
+
job.cancelled = true;
|
|
606
|
+
job.phase = "failed";
|
|
607
|
+
job.error = "cancelled";
|
|
608
|
+
for (const filmId of job.shard_film_ids) {
|
|
609
|
+
await cancelFilmJob(env, filmId);
|
|
610
|
+
}
|
|
611
|
+
await saveScatterJob(env, job);
|
|
612
|
+
return scatterJobToPollView(job);
|
|
613
|
+
}
|
|
614
|
+
//# sourceMappingURL=scatter-orchestrator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scatter-orchestrator.js","sourceRoot":"","sources":["../src/scatter-orchestrator.ts"],"names":[],"mappings":"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"}
|