/** * CLI wrapper del watchdog. La lógica vive en * `src/services/sat/sweep-stale-jobs.service.ts` para que también se pueda * correr desde un cron (`sat-sync.job.ts`) sin duplicar código. * * Uso: * pnpm --filter @horux/api exec tsx scripts/sweep-stale-sat-jobs.ts # dry-run * pnpm --filter @horux/api exec tsx scripts/sweep-stale-sat-jobs.ts --apply # ejecuta * STALE_RUNNING_HOURS=2 pnpm --filter @horux/api exec tsx scripts/sweep-stale-sat-jobs.ts */ import { prisma } from '../src/config/database.js'; import { sweepStaleSatJobs } from '../src/services/sat/sweep-stale-jobs.service.js'; async function main() { const apply = process.argv.includes('--apply'); const pendingHours = Number(process.env.STALE_PENDING_HOURS || 12); const runningHours = Number(process.env.STALE_RUNNING_HOURS || 4); const mode = apply ? 'APPLY' : 'DRY-RUN'; console.log(`=== SAT stale-jobs watchdog [${mode}] ===`); console.log(` pending: nextRetryAt < now − ${pendingHours}h`); console.log(` running: startedAt < now − ${runningHours}h`); console.log(); const result = await sweepStaleSatJobs({ apply, pendingHours, runningHours }); console.log(`Encontrados:`); console.log(` pending stale: ${result.pendingFound}`); console.log(` running stale: ${result.runningFound}`); for (const e of result.entries) { console.log(` ─ ${e.id} tenant=${e.tenantId} kind=${e.kind} edad=${e.ageHours}h`); } if (!apply) { console.log(`\n[DRY-RUN] No se aplicaron cambios. Pasa --apply para marcar como failed.`); } else { console.log(`\nMarcados como failed: pending=${result.pendingMarked} running=${result.runningMarked}`); } await prisma.$disconnect(); } main().catch(async (err) => { console.error('Fatal:', err); await prisma.$disconnect().catch(() => {}); process.exit(1); });