perf: offload SWF→Nitro conversion to a worker-thread pool

The synchronous convertSwfToNitro / extractIconFromSwf calls (pure CPU,
no DB/network) now run in a small worker pool so the main Node event
loop stays free during imports — the dominant import-time CPU spike is
moved off the request thread. The pool degrades gracefully to a
synchronous fallback if workers can't be created, and is skipped in the
test environment.
This commit is contained in:
openhands
2026-08-24 19:02:19 +02:00
parent 7116f49e2b
commit 8d1b09f151
6 changed files with 240 additions and 14 deletions
+55
View File
@@ -0,0 +1,55 @@
import { parentPort } from "node:worker_threads";
import { convertSwfToNitro, extractIconFromSwf } from "./index";
export interface ConvertRequest {
id: number;
type: "convert";
buffer: Buffer;
classname: string;
}
export interface IconRequest {
id: number;
type: "icon";
buffer: Buffer;
classname: string;
}
export type WorkerRequest = ConvertRequest | IconRequest;
export type WorkerResponse =
| {
id: number;
ok: true;
result?: import("./index").ConversionResult;
icon?: Buffer | null;
}
| { id: number; ok: false; error: string };
if (parentPort) {
parentPort.on("message", (msg: WorkerRequest) => {
try {
if (msg.type === "convert") {
const result = convertSwfToNitro(msg.buffer, msg.classname);
parentPort!.postMessage({
id: msg.id,
ok: true,
result,
} satisfies WorkerResponse);
} else {
const icon = extractIconFromSwf(msg.buffer, msg.classname);
parentPort!.postMessage({
id: msg.id,
ok: true,
icon: icon ?? null,
} satisfies WorkerResponse);
}
} catch (err) {
parentPort!.postMessage({
id: msg.id,
ok: false,
error: (err as Error).message,
} satisfies WorkerResponse);
}
});
}