// OGraph Dispatcher — entry point // Starts Loop A (ProjectionWatcher) and Loop B (OcScheduler) independently. import { loadConfig } from './config.js'; import { ProjectionWatcher } from './watcher.js'; import { OcScheduler } from './scheduler.js'; import type { PendingEntry } from './types.js'; function ts(): string { return new Date().toISOString(); } async function main(): Promise { console.log(`[${ts()}] [dispatcher] OGraph Dispatcher starting...`); const config = loadConfig(); console.log(`[${ts()}] [dispatcher] config loaded`); console.log(`[${ts()}] [dispatcher] ograph.endpoint = ${config.ograph.endpoint}`); console.log(`[${ts()}] [dispatcher] ograph.projections = [${config.ograph.projections.join(', ')}]`); console.log(`[${ts()}] [dispatcher] oc.statusEndpoint = ${config.oc.statusEndpoint}`); console.log(`[${ts()}] [dispatcher] oc.minAvailable = ${config.oc.minAvailable}`); console.log(`[${ts()}] [dispatcher] intervals.watcherIdle = ${config.intervals.watcherIdle}ms`); console.log(`[${ts()}] [dispatcher] intervals.watcherActive = ${config.intervals.watcherActive}ms`); console.log(`[${ts()}] [dispatcher] intervals.schedulerIdle = ${config.intervals.schedulerIdle}ms`); console.log(`[${ts()}] [dispatcher] intervals.schedulerActive= ${config.intervals.schedulerActive}ms`); console.log(`[${ts()}] [dispatcher] intervals.cooldownAfterPush = ${config.intervals.cooldownAfterPush}ms`); // Shared pending queue — Watcher writes, Scheduler reads + clears const pending: Map = new Map(); const watcher = new ProjectionWatcher(config, pending); const scheduler = new OcScheduler(config, pending); // Start both loops independently watcher.start(); scheduler.start(); console.log(`[${ts()}] [dispatcher] both loops running. Press Ctrl+C to stop.`); // Graceful shutdown const shutdown = (): void => { console.log(`\n[${ts()}] [dispatcher] shutting down...`); watcher.stop(); scheduler.stop(); process.exit(0); }; process.on('SIGINT', shutdown); process.on('SIGTERM', shutdown); // Keep the process alive (the timers are enough, but be explicit) await new Promise(() => { // never resolves — loops keep running via setTimeout chains }); } main().catch((err: unknown) => { console.error(`[${new Date().toISOString()}] [dispatcher] fatal: ${err instanceof Error ? err.message : String(err)}`); process.exit(1); });