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 committed 2026-08-24 19:02:19 +02:00
1 parent 7116f49e2b
commit 8d1b09f151
6 files changed
+240 -14

No files matched your search

+19 -6
View File
@@ -43,8 +43,8 @@ vi.mock("@/lib/services/import/core/download", async () => {
};
});
vi.mock("@/lib/services/swf-to-nitro", () => ({
convertSwfToNitro: vi.fn(() => ({
vi.mock("@/lib/services/swf-to-nitro", () => {
const convertSwfToNitro = vi.fn((_buffer: Buffer, _classname: string) => ({
bundle: Buffer.alloc(256, 0x42),
classname: "n/a",
dimensions: { x: 1, y: 1, z: 1 },
@@ -61,10 +61,23 @@ vi.mock("@/lib/services/swf-to-nitro", () => ({
defaultdir: 0,
partcolors: { color: [] },
},
})),
extractIconFromSwf: vi.fn(() => Buffer.from("fake-icon")),
parseNitroBundle: vi.fn(() => ({ json: null })),
}));
}));
const extractIconFromSwf = vi.fn((_buffer: Buffer, _classname: string) =>
Buffer.from("fake-icon"),
);
const parseNitroBundle = vi.fn(() => ({ json: null }));
return {
convertSwfToNitro,
extractIconFromSwf,
parseNitroBundle,
convertSwfToNitroAsync: vi.fn(async (buffer: Buffer, classname: string) =>
convertSwfToNitro(buffer, classname),
),
extractIconFromSwfAsync: vi.fn(async (buffer: Buffer, classname: string) =>
extractIconFromSwf(buffer, classname),
),
};
});
vi.mock("@/lib/services/habbo-furnidata-cache", () => ({
lookupOfficialHabboFurni: vi.fn(async () => null),