import 'reflect-metadata'; import { Logger } from '@nestjs/common'; import { NestFactory } from '@nestjs/core'; import { WorkerModule } from './worker.module'; import { LocationFlusherService } from './modules/locations/location-flusher.service'; /** * نقطة دخول الـ worker — مهام غير متزامنة خارج مسار الطلب (docs/09، docs/17 H3/H4). * حالياً: تفريغ لقطات المواقع ونقاط المسار من Redis إلى القاعدة دورياً. */ const FLUSH_INTERVAL_MS = parseInt(process.env.LOC_FLUSH_INTERVAL_MS ?? '5000', 10); async function bootstrap() { const log = new Logger('Worker'); const app = await NestFactory.createApplicationContext(WorkerModule, { logger: ['error', 'warn', 'log'], }); const flusher = app.get(LocationFlusherService); log.log( `Tripz worker up. locationFlush=${FLUSH_INTERVAL_MS}ms ` + `queuePrefix=${process.env.QUEUE_PREFIX ?? 'tripz_'} redisDb=${process.env.REDIS_DB ?? '3'}`, ); // قفل بسيط: دورة لا تبدأ قبل أن تنتهي سابقتها — دفعة بطيئة يجب ألّا تتراكب // مع التالية فتُدرَج النقاط مرتين أو تُغرق القاعدة. let running = false; const timer = setInterval(async () => { if (running) return; running = true; try { await flusher.flush(); } catch (e: any) { log.error(`flush cycle failed: ${e?.message}`); } finally { running = false; } }, FLUSH_INTERVAL_MS); const shutdown = async (signal: string) => { log.log(`${signal} — draining…`); clearInterval(timer); // تفريغة أخيرة حتى لا تضيع اللقطات المعلّقة عند إعادة النشر. try { await flusher.flush(); } catch (e: any) { log.warn(`final flush failed: ${e?.message}`); } await app.close(); process.exit(0); }; process.on('SIGTERM', () => void shutdown('SIGTERM')); process.on('SIGINT', () => void shutdown('SIGINT')); } bootstrap();