import { Worker, Job } from "bullmq"; import { redisConnection } from "../connection"; import { OcrJobData } from "../queues"; import { io } from "../../socket"; import { runOcrProcessor } from "../processors/ocrProcessor"; function emitJobUpdate( socketId: string | undefined, jobId: string, status: "active" | "completed" | "failed", payload: Record ) { const event = "job:update"; const data = { jobId, jobType: "ocr", status, ...payload }; if (socketId && io) { io.to(socketId).emit(event, data); } else if (io) { io.emit(event, data); } } async function processOcrJob(job: Job) { const { socketId, files } = job.data; const jobId = job.id ?? job.name; emitJobUpdate(socketId, jobId, "active", { message: "OCR processing started…" }); try { const rows = await runOcrProcessor({ files }); emitJobUpdate(socketId, jobId, "completed", { result: { rows } }); return rows; } catch (err: any) { const errorMsg = err?.message ?? String(err); emitJobUpdate(socketId, jobId, "failed", { error: errorMsg }); throw err; } } export function startOcrWorker() { const worker = new Worker("ocr-jobs", processOcrJob, { connection: redisConnection, concurrency: 2, // OCR service allows 2 concurrent }); worker.on("completed", (job) => { console.log(`[ocrWorker] job ${job.id} completed`); }); worker.on("failed", (job, err) => { console.error(`[ocrWorker] job ${job?.id} failed:`, err.message); }); console.log("[ocrWorker] started"); return worker; }