import { mkdirSync } from 'node:fs'; import { join } from 'node:path'; import { loadConfig } from './config.js'; import { openDb } from './db.js'; import { createSalt } from './salt.js'; import { loadGeo } from './geo.js'; import { scheduleNightly } from './jobs.js'; import { createPublicServer, createAdminServer } from './server.js'; const config = loadConfig(process.env); mkdirSync(config.dataDir, { recursive: true }); const db = openDb(join(config.dataDir, 'analytics.db')); const geo = loadGeo(config.geoFile || join(config.dataDir, 'geo.csv')); if (geo.size) console.log(`Analytics: ${geo.size} Länder-Bereiche geladen`); const publicServer = createPublicServer({ config, db, geo, salt: createSalt() }); const servers = [ ['öffentlich', publicServer, config.port], ['intern (Admin)', createAdminServer({ config, db, onSitesChanged: () => publicServer.invalidateSites() }), config.adminPort], ]; for (const [name, server, port] of servers) { server.on('error', (e) => { console.error(`Analytics-Listener ${name} (Port ${port}):`, e.message); process.exit(1); }); server.listen(port, () => console.log(`Analytics-Dienst ${name} auf Port ${port}`)); } // Nachtjob: täglich 02:30 Europe/Berlin und einmal 60 s nach dem Start const nightly = scheduleNightly(db); process.on('SIGTERM', () => { nightly.stop(); let open = servers.length; const done = () => { if (--open === 0) { db.close(); process.exit(0); } }; for (const [, server] of servers) { server.close(done); server.closeIdleConnections?.(); } setTimeout(() => process.exit(0), 5000).unref(); });