feat: implement background job system with queue, worker, scheduler, and handlers

- Add job queue abstraction (InMemoryQueue and Redis/BullMQ adapter)
- Add polling worker with retry logic and exponential backoff
- Add 6 job handlers: darkwatch.scan, voiceprint.batch, hometitle.scan,
  removebrokers.process, reports.generate, notifications.send
- Add cron-based scheduler with tier-appropriate frequencies
  (Basic/Plus/Premium)
- Add tRPC scheduler router for admin (runJobNow, getJobStatus, etc.)
- Add entry point with graceful shutdown support
- Achieve 100% test pass rate for new job system
This commit is contained in:
2026-05-25 17:16:21 -04:00
parent 659ab9b71a
commit eb8e57c674
19 changed files with 1429 additions and 0 deletions

View File

@@ -0,0 +1,34 @@
import type { JobPayload, JobType } from "../queue";
export type JobHandler<T extends JobType = JobType> = (payload: JobPayload[T]) => Promise<void>;
export type HandlerMap = {
[K in JobType]: JobHandler<K>;
};
let handlers: HandlerMap | null = null;
export function getHandlers(): HandlerMap {
if (!handlers) {
handlers = {
"darkwatch.scan": require("./darkwatch.scan").handler,
"voiceprint.batch": require("./voiceprint.batch").handler,
"hometitle.scan": require("./hometitle.scan").handler,
"removebrokers.process": require("./removebrokers.process").handler,
"reports.generate": require("./reports.generate").handler,
"notifications.send": require("./notifications.send").handler,
};
}
return handlers;
}
export function setHandlers(mock: Partial<HandlerMap>): void {
handlers = {
"darkwatch.scan": mock["darkwatch.scan"] ?? (async () => {}),
"voiceprint.batch": mock["voiceprint.batch"] ?? (async () => {}),
"hometitle.scan": mock["hometitle.scan"] ?? (async () => {}),
"removebrokers.process": mock["removebrokers.process"] ?? (async () => {}),
"reports.generate": mock["reports.generate"] ?? (async () => {}),
"notifications.send": mock["notifications.send"] ?? (async () => {}),
};
}