mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-04 07:19:52 +00:00
refactor(producer): make sequencer the sole writer of job.duration/totalFrames
The probe stage previously assigned `job.duration` and `job.totalFrames` inside its body AND the sequencer re-asserted them after the call to restore TS narrowing. Two writers for the same field is a maintenance hazard — a future refactor could drop one and create a silent skew. Move ownership: the stage computes `duration` and `totalFrames` and returns them; the sequencer is the sole writer onto the `RenderJob`. This also aligns with the eventual chunk-worker model where a chunk running in a separate process cannot mutate the orchestrator's `job`. No observable behavior change. `job.duration` / `job.totalFrames` end up with the same values; the zero-duration `throw` still happens inside the stage (now using the local `duration` constant) before any sequencer-side assignment. Verified by: - `bun run --filter @hyperframes/producer typecheck` clean - `bun test packages/producer/src/services/` 175 pass / 1 pre-existing unrelated failure on `main` Review feedback addressed: vanceingalls on #719. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -13,8 +13,11 @@
|
||||
* plan lists recompile as a sibling phase.
|
||||
* - `composition` (videos/audios/duration) is mutated in place — callers
|
||||
* downstream see the reconciled view through the same object reference.
|
||||
* - `job.duration` and `job.totalFrames` are assigned at the same code
|
||||
* points.
|
||||
* - The stage computes the final composition `duration` and `totalFrames`
|
||||
* and returns them. Assigning those values onto the `RenderJob` is the
|
||||
* sequencer's responsibility — a future chunk worker can't mutate the
|
||||
* orchestrator's `job` object, and keeping the assignment in one place
|
||||
* prevents the same value living in two writers.
|
||||
* - The "Composition duration is 0" diagnostic builds the same hint
|
||||
* string from the same console-buffer regex and `__timelines` probe.
|
||||
* - The post-probe "failed network requests" warning fires with the same
|
||||
@@ -288,10 +291,8 @@ export async function runProbeStage(input: ProbeStageInput): Promise<ProbeStageR
|
||||
}
|
||||
const browserProbeMs = Date.now() - probeStart;
|
||||
|
||||
job.duration = composition.duration;
|
||||
job.totalFrames = Math.ceil(composition.duration * fpsToNumber(job.config.fps));
|
||||
const duration = composition.duration;
|
||||
const totalFrames = job.totalFrames;
|
||||
const totalFrames = Math.ceil(duration * fpsToNumber(job.config.fps));
|
||||
|
||||
if (duration <= 0) {
|
||||
// Gather diagnostics to help users understand why the render would produce a black video.
|
||||
|
||||
@@ -2153,10 +2153,8 @@ export async function executeRenderJob(
|
||||
fileServer = probeResult.fileServer;
|
||||
probeSession = probeResult.probeSession;
|
||||
lastBrowserConsole = probeResult.lastBrowserConsole;
|
||||
// Re-assign through the typed result so the rest of the function sees
|
||||
// `job.duration` and `job.totalFrames` narrowed to `number` — the
|
||||
// assignments happened inside `runProbeStage`, but mirroring them here
|
||||
// restores TypeScript's control-flow narrowing.
|
||||
// The probe stage produces `duration` / `totalFrames` values; the
|
||||
// sequencer owns the `RenderJob` and writes them onto it.
|
||||
job.duration = probeResult.duration;
|
||||
job.totalFrames = probeResult.totalFrames;
|
||||
const totalFrames = probeResult.totalFrames;
|
||||
|
||||
Reference in New Issue
Block a user