require("dotenv/config"); const { getConfig } = require("./config"); const { initTracing, shutdownTracing } = require("./observability/tracing"); const config = getConfig(); initTracing(config); const { buildApp } = require("./app"); async function main() { const app = await buildApp(); app.log.info( { jobDriver: app.config.jobDriver, jobsEnabled: app.config.jobsEnabled, }, "API process started", ); const { host, port } = app.config; await app.listen({ host, port }); let shuttingDown = false; const shutdown = async (signal) => { if (shuttingDown) return; shuttingDown = true; app.log.info({ signal }, "Graceful shutdown start"); const timeoutMs = 10_000; const forceTimer = setTimeout(() => { app.log.error({ timeoutMs }, "Graceful shutdown timeout, force exit"); process.exit(1); }, timeoutMs); forceTimer.unref?.(); let exitCode = 0; try { await app.close(); } catch (error) { app.log.error({ err: error }, "Graceful shutdown failed"); exitCode = 1; } try { await shutdownTracing(); } catch (error) { app.log.error({ err: error }, "OTel shutdown failed"); exitCode = 1; } clearTimeout(forceTimer); app.log.info({ exitCode }, "Graceful shutdown completed"); process.exit(exitCode); }; process.on("SIGTERM", () => shutdown("SIGTERM")); process.on("SIGINT", () => shutdown("SIGINT")); } main().catch(async (err) => { // eslint-disable-next-line no-console console.error(err); try { await shutdownTracing(); } catch { // The startup error remains authoritative; shutdown is best effort here. } process.exit(1); });