Files
pn-new-crm/src/worker.ts
Matt Ciaccio c5b41ca4b5 fix(audit): CRITICAL — wire 5 missing workers + bulk-archive side-effects + restore-button hover
C1: src/worker.ts and src/server.ts only imported 5 of 10 BullMQ
workers. ai/bulk/maintenance/reports/webhooks were never started, so
in production: webhooks never delivered, no maintenance crons (DB
backups, session cleanup, retention sweeps, alerts, analytics refresh,
calendar sync), no scheduled reports, no AI features, no async bulk.
All 10 are now imported and held against GC.

R2-C1: Bulk archive's runBulk callback discarded the return value
from archiveClientWithDecisions, so Documenso envelopes marked for
void in the wizard were never queued and next-in-line notifications
never fired. Now we collect the per-archive (dossier, result) pairs
and replay the same post-commit fan-out the single-client route uses.

R2-C2: Archived-client header's Restore icon was hovering destructive-
red because an unconditional hover:text-foreground was overriding the
later conditional. Restore now hovers emerald; archive still hovers
red.

1175/1175 vitest passing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 22:03:47 +02:00

60 lines
1.8 KiB
TypeScript

/**
* Worker entry point for the crm-worker container.
*
* Imports all BullMQ workers and registers recurring job schedules.
* In production this runs as a separate process (Dockerfile.worker).
* In development, server.ts imports workers inline instead.
*/
import { logger } from '@/lib/logger';
import { registerRecurringJobs } from '@/lib/queue/scheduler';
// Import all workers - the act of importing starts them
import { emailWorker } from '@/lib/queue/workers/email';
import { documentsWorker } from '@/lib/queue/workers/documents';
import { notificationsWorker } from '@/lib/queue/workers/notifications';
import { importWorker } from '@/lib/queue/workers/import';
import { exportWorker } from '@/lib/queue/workers/export';
import { aiWorker } from '@/lib/queue/workers/ai';
import { bulkWorker } from '@/lib/queue/workers/bulk';
import { maintenanceWorker } from '@/lib/queue/workers/maintenance';
import { reportsWorker } from '@/lib/queue/workers/reports';
import { webhooksWorker } from '@/lib/queue/workers/webhooks';
// Keep references so workers aren't GC'd
const workers = [
emailWorker,
documentsWorker,
notificationsWorker,
importWorker,
exportWorker,
aiWorker,
bulkWorker,
maintenanceWorker,
reportsWorker,
webhooksWorker,
];
async function main(): Promise<void> {
logger.info({ workerCount: workers.length }, 'BullMQ workers started');
await registerRecurringJobs();
logger.info('Recurring jobs registered');
// Graceful shutdown
const shutdown = async () => {
logger.info('Shutting down workers...');
await Promise.all(workers.map((w) => w.close()));
logger.info('All workers closed');
process.exit(0);
};
process.on('SIGTERM', shutdown);
process.on('SIGINT', shutdown);
}
main().catch((err) => {
logger.error(err, 'Worker process failed to start');
process.exit(1);
});