import type { Database } from 'bun:sqlite'; import { setDb } from '../db/locator'; import { WebhookManager } from '../services/webhook-manager'; import { GroupSyncService } from '../services/group-sync'; import { ResponseQueue } from '../services/response-queue'; import { RemindersService } from '../services/reminders'; import { MaintenanceService } from '../services/maintenance'; export async function startServices(_db: Database): Promise { // Exponer la DB globalmente vía locator para servicios que lo usen. try { setDb(_db); } catch {} await WebhookManager.registerWebhook(); // Add small delay to allow webhook to propagate await new Promise(resolve => setTimeout(resolve, 1000)); const isActive = await WebhookManager.verifyWebhook(); if (!isActive) { console.error('❌ Webhook verification failed - retrying in 2 seconds...'); await new Promise(resolve => setTimeout(resolve, 2000)); const isActiveRetry = await WebhookManager.verifyWebhook(); if (!isActiveRetry) { console.error('❌ Webhook verification failed after retry'); process.exit(1); } } // Initialize groups - critical for operation await GroupSyncService.checkInitialGroups(); // Start groups scheduler (periodic sync of groups) try { GroupSyncService.startGroupsScheduler(); console.log('✅ Group scheduler started'); } catch (e) { console.error('⚠️ Failed to start Group scheduler:', e); } // Initial members sync (non-blocking if fails) try { await GroupSyncService.syncMembersForActiveGroups(); GroupSyncService.startMembersScheduler(); console.log('✅ Group members scheduler started'); } catch (e) { console.error('⚠️ Failed to run initial members sync or start scheduler:', e); } // Start response queue worker (background) try { await ResponseQueue.process(); console.log('✅ ResponseQueue worker started'); // Start cleanup scheduler (daily retention) ResponseQueue.startCleanupScheduler(); console.log('✅ ResponseQueue cleanup scheduler started'); RemindersService.start(); console.log('✅ RemindersService started'); } catch (e) { console.error('❌ Failed to start ResponseQueue worker or cleanup scheduler:', e); } // Mantenimiento (cleanup de miembros inactivos) try { MaintenanceService.start(); console.log('✅ MaintenanceService started'); // Ejecutar reconciliación de alias una vez al arranque (one-shot) try { await MaintenanceService.reconcileAliasUsersOnce(); console.log('✅ MaintenanceService: reconciliación de alias ejecutada (one-shot)'); } catch (e2) { console.error('⚠️ Failed to run alias reconciliation one-shot:', e2); } } catch (e) { console.error('⚠️ Failed to start MaintenanceService:', e); } } export function stopServices(): void { try { ResponseQueue.stopCleanupScheduler(); } catch {} try { // No existe un "stop" público de workers; paramos el lazo (ResponseQueue as any).stop?.(); } catch {} try { RemindersService.stop(); } catch {} try { GroupSyncService.stopGroupsScheduler(); GroupSyncService.stopMembersScheduler(); } catch {} try { MaintenanceService.stop(); } catch {} }