import { pool } from "../db/pool.ts"; import { despachar } from "./outbox.ts"; let corriendo = false; /** * Vacía la bandeja de salida cada cierto tiempo. * * Es un intervalo y no una cola de verdad a propósito: hay un solo negocio, el * CRM estrangula a ~1 petición cada 0.65 s, y el volumen real son unas pocas * citas al día. Redis y un worker aparte serían infraestructura sin problema * que resolver. Cuando haya varios negocios habrá que revisarlo, porque el * estrangulamiento es **por token** y estos despachos serían secuenciales. * * La guarda `corriendo` evita que dos vueltas se solapen: dos escrituras * concurrentes sobre la misma cita corren contra una base que ya cambió. */ export function arrancarWorker(intervaloMs = 60_000): NodeJS.Timeout { const tick = async () => { if (corriendo) return; corriendo = true; try { const { rows } = await pool.query<{ business_id: number }>( `SELECT DISTINCT business_id FROM crm_outbox WHERE status = 'pendiente'` ); for (const r of rows) { const res = await despachar(r.business_id, 25); if (res.tomadas) { console.log( `[crm-worker] negocio ${r.business_id}: ${res.confirmadas} confirmadas, ` + `${res.fallidas} fallidas, ${res.indeterminadas} indeterminadas` ); } } } catch (e) { // Un fallo aquí no debe tumbar el servidor: la bandeja seguirá llena y el // panel de clientes lo enseña, que es justo para lo que existe. console.error("[crm-worker]", (e as Error).message); } finally { corriendo = false; } }; const t = setInterval(tick, intervaloMs); // No mantiene vivo el proceso: si el servidor se cierra, no hay que esperarlo. t.unref?.(); return t; }