feat(gateway): implement separate Piscina pools for text and media analysis to optimize processing

This commit is contained in:
asepharyana committed 2026-08-31 22:59:27 +07:00
1 parent 3ce594d9b5
commit 12cc956329
9 files changed
+272 -65

No files matched your search

@@ -6,7 +6,16 @@ import { config } from "../../shared/config/config.js";
import type { MessageRecord } from "../message-capture/types.js";
// ---------------------------------------------------------------------------
// Piscina worker pool (shared by batch + individual pipelines)
// Piscina worker pools (2026-08-31: split text vs media)
//
// Both the batch and individual-fallback pipelines used to share ONE pool.
// A conversation batch containing images/stickers/embeds routes through
// runMediaBatch (download + vision + LLM — tens of seconds per batch), and
// Piscina hands each worker thread exactly one task at a time. With a small
// fixed thread count, a handful of slow media batches could occupy every
// thread and leave fast text-only batches for OTHER conversations queued
// behind them for the whole media duration. Text and media now get their
// own dedicated pools so a media backlog can never starve text analysis.
// ---------------------------------------------------------------------------
function getAnalysisWorkerUrl(): URL {
@@ -25,12 +34,32 @@ function getAnalysisWorkerUrl(): URL {
return candidates[2];
}
export const workerPool = new Piscina({
filename: fileURLToPath(getAnalysisWorkerUrl()),
const analysisWorkerFilename = fileURLToPath(getAnalysisWorkerUrl());
/** Dedicated pool for text-only batch/individual analysis jobs. */
export const textWorkerPool = new Piscina({
filename: analysisWorkerFilename,
execArgv: process.execArgv,
maxThreads: config.PISCINA_MAX_THREADS ?? availableParallelism(),
});
/**
* Dedicated pool for jobs whose batch contains at least one message with
* media (attachments/stickers/embeds). Kept separate so slow image/vision
* analysis never blocks the text pool above.
*/
export const mediaWorkerPool = new Piscina({
filename: analysisWorkerFilename,
execArgv: process.execArgv,
maxThreads: config.PISCINA_MEDIA_MAX_THREADS ?? 2,
});
/**
* @deprecated Use `textWorkerPool` or `mediaWorkerPool` directly. Kept as an
* alias to the text pool only for anything not yet migrated.
*/
export const workerPool = textWorkerPool;
/**
* Gets the conversation key for a message (thread_id or channel_id).
*/