mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-10-30 09:16:55 +00:00
fix(producer): start segmented render workers together so slow media waits overlap (#5573)
* fix(producer): start segmented render workers together so slow media waits overlap Each worker's page load used to wait for the previous worker's media, fonts and Tailwind to be ready, so a slow readiness wait was paid once per worker. Open every worker session at once, as non-segmented parallel capture already does. * fix(producer): trim the worker-opening comment * fix(producer): name the worker-opening helper instead of commenting it
This commit is contained in:
@@ -700,6 +700,36 @@ describe("runCaptureSegmentedStage", () => {
|
||||
expect(createdSessionConfigs).toEqual([expect.objectContaining({ enableBrowserPool: false })]);
|
||||
});
|
||||
|
||||
it("opens every worker's session together, so readiness waits overlap", async () => {
|
||||
let opening = 0;
|
||||
let mostOpeningAtOnce = 0;
|
||||
let id = 0;
|
||||
const result = await runCaptureSegmentedStage({
|
||||
...fakeStageInput({ totalFrames: 9 }),
|
||||
probeSession: null,
|
||||
segmentFrames: 3,
|
||||
segmentDir: join(fixtureRoot, "concurrent-open"),
|
||||
workerCount: 3,
|
||||
sessionFactory: {
|
||||
create: async () => {
|
||||
mostOpeningAtOnce = Math.max(mostOpeningAtOnce, ++opening);
|
||||
await new Promise((resolve) => setImmediate(resolve));
|
||||
opening--;
|
||||
return fakeSession(id++);
|
||||
},
|
||||
},
|
||||
deps: {
|
||||
spawnEncoder: mock(async () => okEncoder()),
|
||||
captureFrame: mock(async () => ({ buffer: Buffer.alloc(1) })),
|
||||
concat: mock(async () => ({ success: true as const })),
|
||||
closeSession: mock(async () => {}),
|
||||
removeFile: () => {},
|
||||
},
|
||||
});
|
||||
expect(result.success).toBe(true);
|
||||
expect(mostOpeningAtOnce).toBe(3);
|
||||
});
|
||||
|
||||
it("closes a fresh session whose initialization fails", async () => {
|
||||
closeCaptureSession.mockClear();
|
||||
failInitializeSession = true;
|
||||
|
||||
@@ -408,6 +408,18 @@ async function createSegmentWorker(run: SegmentRun, id: number): Promise<Segment
|
||||
};
|
||||
}
|
||||
|
||||
async function openSegmentWorkersTogether(
|
||||
run: SegmentRun,
|
||||
workersToCloseLater: SegmentWorker[],
|
||||
): Promise<void> {
|
||||
const opened = await Promise.allSettled(
|
||||
Array.from({ length: run.workerCount }, (_, id) => createSegmentWorker(run, id)),
|
||||
);
|
||||
for (const o of opened) if (o.status === "fulfilled") workersToCloseLater.push(o.value);
|
||||
const failure = opened.find((o) => o.status === "rejected");
|
||||
if (failure && failure.status === "rejected") throw failure.reason;
|
||||
}
|
||||
|
||||
/** Close this worker's browser and open a fresh one at a segment boundary. */
|
||||
async function recycleWorkerSession(
|
||||
run: SegmentRun,
|
||||
@@ -585,7 +597,7 @@ export async function runCaptureSegmentedStage(
|
||||
|
||||
try {
|
||||
assertNotAborted();
|
||||
for (let id = 0; id < run.workerCount; id++) workers.push(await createSegmentWorker(run, id));
|
||||
await openSegmentWorkersTogether(run, workers);
|
||||
// allSettled, not all: closing a session out from under a worker that is
|
||||
// still capturing orphans its ffmpeg and races the CDP connection, so
|
||||
// every worker has to stop before the finally runs. The first error is
|
||||
|
||||
Reference in New Issue
Block a user