mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-04 16:42:27 +00:00
## Summary Fixes three issues identified in the [post-merge review](https://github.com/heygen-com/hyperframes/pull/596#pullrequestreview-4214283515) of PR #596: - **P1 (cache bypass):** When `extractCacheDir` is set, extracted frames live outside `compiledDir`, so `createCompiledFrameSrcResolver` rejects them and every frame falls back to base64 data URIs. Fix: symlink cached frame directories into `compiledDir/__hyperframes_video_frames/` after extraction and remap `framePaths` so the served-frame fast path works. - **P2 (pooled browser stale state):** `closeCaptureSession` force-killed the Chrome process on timeout via raw `SIGKILL` without clearing `pooledBrowser` / `pooledBrowserRefCount`, leaving other sessions with a dead browser reference. Fix: add `forceReleaseBrowser()` in `browserManager` that atomically clears pool state before killing the process. - **P3 (reserved chars in URLs):** `createCompiledFrameSrcResolver` encodes path segments with `encodeURIComponent`, but the file server used `c.req.path` (which only applies `decodeURI`) to look up files on disk. Video IDs containing `#`, `?`, or `%` produced 404s. Fix: apply `decodeURIComponent` per path segment in the file server's catch-all route. ## Test plan - [x] `createCompiledFrameSrcResolver` tests: symlinked cache paths resolve to served URLs; cache-external paths return null; reserved characters encode correctly - [x] `forceReleaseBrowser` tests: kills process + disconnects; tolerates already-killed process - [x] `createFileServer` test: `video%231/frame.jpg` serves file from `video#1/frame.jpg` on disk - [x] Typecheck: engine + producer pass - [x] Lint + format: 0 warnings, 0 errors
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
|
||||
import { buildChromeArgs } from "./browserManager.js";
|
||||
import { buildChromeArgs, forceReleaseBrowser } from "./browserManager.js";
|
||||
|
||||
describe("buildChromeArgs browser GPU mode", () => {
|
||||
const base = { width: 1920, height: 1080 };
|
||||
@@ -46,3 +46,33 @@ describe("buildChromeArgs browser GPU mode", () => {
|
||||
expect(args).not.toContain("--use-angle=metal");
|
||||
});
|
||||
});
|
||||
|
||||
describe("forceReleaseBrowser", () => {
|
||||
it("kills the browser process and disconnects", () => {
|
||||
const killFn = vi.fn(() => true);
|
||||
const disconnectFn = vi.fn();
|
||||
const mockBrowser = {
|
||||
process: () => ({ kill: killFn, killed: false }),
|
||||
disconnect: disconnectFn,
|
||||
} as any;
|
||||
|
||||
forceReleaseBrowser(mockBrowser);
|
||||
|
||||
expect(killFn).toHaveBeenCalledWith("SIGKILL");
|
||||
expect(disconnectFn).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("tolerates an already-killed process", () => {
|
||||
const killFn = vi.fn();
|
||||
const disconnectFn = vi.fn();
|
||||
const mockBrowser = {
|
||||
process: () => ({ kill: killFn, killed: true }),
|
||||
disconnect: disconnectFn,
|
||||
} as any;
|
||||
|
||||
forceReleaseBrowser(mockBrowser);
|
||||
|
||||
expect(killFn).not.toHaveBeenCalled();
|
||||
expect(disconnectFn).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user