import { JobQueue } from './types.js' import { MemoryQueue } from './MemoryQueue.js' import { PgBossQueue } from './PgBossQueue.js' /** * 任务队列工厂类 * * 根据环境变量自动选择队列实现: * - QUEUE_TYPE=memory: 使用MemoryQueue(内存队列) * - QUEUE_TYPE=pgboss: 使用PgBossQueue(Postgres队列) * - QUEUE_TYPE=database: 别名,指向pgboss * * 零代码切换: * - 本地开发:不配置QUEUE_TYPE,默认使用memory * - Postgres-Only架构:配置QUEUE_TYPE=pgboss * - 多实例部署:配置QUEUE_TYPE=pgboss(自动负载均衡) * * @example * ```typescript * import { jobQueue } from '@/common/jobs' * * // 业务代码不关心具体实现 * const job = await jobQueue.push('asl:screening', { projectId: 123 }) * ``` */ export class JobFactory { private static instance: JobQueue | null = null /** * 获取任务队列实例(单例模式) */ static getInstance(): JobQueue { if (!this.instance) { this.instance = this.createQueue() } return this.instance } /** * 创建任务队列 */ private static createQueue(): JobQueue { const queueType = process.env.QUEUE_TYPE || 'memory' switch (queueType) { case 'memory': return this.createMemoryQueue() case 'pgboss': case 'database': // 别名 return this.createPgBossQueue() default: console.warn(`[JobFactory] Unknown QUEUE_TYPE: ${queueType}, fallback to memory`) return this.createMemoryQueue() } } /** * 创建内存队列 */ private static createMemoryQueue(): MemoryQueue { console.log('[JobFactory] Using MemoryQueue') const queue = new MemoryQueue() // 定期清理已完成的任务(避免内存泄漏) if (process.env.NODE_ENV !== 'test') { setInterval(() => { queue.cleanup() }, 60 * 60 * 1000) // 每小时清理一次 } return queue } /** * 创建PgBoss队列 */ private static createPgBossQueue(): PgBossQueue { const databaseUrl = process.env.DATABASE_URL if (!databaseUrl) { throw new Error( '[JobFactory] DATABASE_URL is required when QUEUE_TYPE=pgboss' ) } console.log('[JobFactory] Using PgBossQueue (Postgres-Only架构)') const queue = new PgBossQueue(databaseUrl, 'platform_schema') // 启动队列(异步) queue.start().catch(err => { console.error('[JobFactory] Failed to start PgBossQueue:', err) }) // 定期清理缓存中的已完成任务 if (process.env.NODE_ENV !== 'test') { setInterval(() => { queue.cleanup() }, 60 * 60 * 1000) // 每小时清理一次 } return queue } /** * 重置实例(用于测试) */ static reset(): void { this.instance = null } }