{"version":3,"file":"start.cjs","sources":["../../../packages/engine-server/src/start.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport {\n\tcreateContainer,\n\tcreateDefaultLogger,\n\tcreateSentryLoggerHandler,\n\tgetServerVersion,\n\tisDebugMode,\n\tlistenOnProcessTermination,\n\tprintStartInfo,\n\tresolveServerConfig,\n\tserverConfigSchema,\n\tTerminationJob,\n} from '@contember/engine-http'\nimport loadPlugins from './loadPlugins'\nimport cluster from 'node:cluster'\nimport * as os from 'node:os'\nimport { timeout } from './utils'\nimport { getClusterProcessType, notifyWorkerStarted, WorkerManager } from './cluster'\n\nconst logger = createDefaultLogger()\nprocess.on('warning', message => {\n\tlogger.warn(message)\n})\n;(async () => {\n\tconst isDebug = isDebugMode()\n\n\tconst version = await getServerVersion()\n\tprintStartInfo({ version, isDebug }, logger)\n\tconst plugins = await loadPlugins()\n\tconst { serverConfig, projectConfigResolver, tenantConfigResolver } = await resolveServerConfig({ plugins, serverConfigSchema })\n\n\tif (process.argv[2] === 'validate') {\n\t\tprocess.exit(0)\n\t}\n\n\tconst sentryhandler = createSentryLoggerHandler(serverConfig.logging?.sentry?.dsn)\n\tif (sentryhandler !== null) {\n\t\tlogger.addHandler(sentryhandler)\n\t}\n\n\tconst workerConfig = serverConfig.workerCount || 1\n\n\tconst workerCount = workerConfig === 'auto' ? os.cpus().length : Number(workerConfig)\n\tconst isClusterMode = serverConfig.workerCount !== undefined\n\n\tconst processType = getClusterProcessType(isClusterMode)\n\n\tconst container = createContainer({\n\t\tdebugMode: isDebug,\n\t\tserverConfig,\n\t\tprojectConfigResolver,\n\t\ttenantConfigResolver,\n\t\tplugins,\n\t\tprocessType,\n\t\tversion,\n\t\tlogger,\n\t})\n\n\tlet initializedProjects: string[] = []\n\tconst terminationJobs: TerminationJob[] = []\n\tlistenOnProcessTermination(terminationJobs, logger)\n\n\tif (cluster.isMaster) {\n\t\tconst monitoringPort = serverConfig.monitoringPort\n\t\tconst monitoringServer = container.monitoringKoa.listen(monitoringPort, () => {\n\t\t\tlogger.info(`Monitoring running on http://localhost:${monitoringPort}`)\n\t\t})\n\t\tterminationJobs.push(async () => {\n\t\t\tawait new Promise<any>(resolve => monitoringServer.close(resolve))\n\t\t\tlogger.info('Monitoring server terminated')\n\t\t})\n\t\tif (!serverConfig.projectGroup) {\n\t\t\tinitializedProjects = await container.initializer.initialize()\n\t\t}\n\t}\n\n\tconst port = serverConfig.port\n\tconst printStarted = () => {\n\t\tif (serverConfig.projectGroup) {\n\t\t\tlogger.info('Contember Cloud running')\n\t\t} else {\n\t\t\tlogger.info(`Contember API running on http://localhost:${port}`)\n\t\t}\n\t\tif (initializedProjects.length) {\n\t\t\tlogger.info(`Initialized projects: ${initializedProjects.join(', ')}`)\n\t\t}\n\t}\n\n\tconst startApplication = async () => {\n\t\tconst httpServerPromise = container.application.listen()\n\t\tterminationJobs.push(async () => {\n\t\t\tawait (await httpServerPromise).close()\n\t\t\tlogger.info('API server terminated')\n\t\t})\n\t\tawait httpServerPromise\n\t}\n\n\tconst startWorker = async (workerName: string) => {\n\t\tconst worker = container.applicationWorkers.getWorker(workerName)\n\t\tconst runningWorker = worker.run({\n\t\t\tlogger,\n\t\t\tonError: e => {\n\t\t\t\tlogger.crit(e)\n\t\t\t\tprocess.exit(1)\n\t\t\t},\n\t\t})\n\t\tterminationJobs.push(async () => {\n\t\t\t(await runningWorker).end()\n\t\t})\n\t\tawait runningWorker\n\t\tlogger.info(`Contember Worker ${workerName} started.`)\n\n\t}\n\n\tconst applicationWorker = serverConfig.applicationWorker\n\tif (applicationWorker && applicationWorker !== 'all') {\n\t\tawait startWorker(applicationWorker)\n\t\tif (isClusterMode) {\n\t\t\tnotifyWorkerStarted()\n\t\t}\n\t} else if (isClusterMode) {\n\t\tif (cluster.isMaster) {\n\t\t\tlogger.info(`Master ${process.pid} is running`)\n\t\t\tconst workerManager = new WorkerManager()\n\t\t\tterminationJobs.push(async ({ signal }) => {\n\t\t\t\tawait workerManager.terminate(signal)\n\t\t\t\tlogger.info('Workers terminated')\n\t\t\t})\n\n\t\t\tawait workerManager.start({ workerCount })\n\n\t\t\tif (applicationWorker === 'all') {\n\t\t\t\tfor (const workerName of container.applicationWorkers.getWorkerNames()) {\n\t\t\t\t\tawait workerManager.start({\n\t\t\t\t\t\tworkerCount, env: {\n\t\t\t\t\t\t\tCONTEMBER_APPLICATION_WORKER: workerName,\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t\tprintStarted()\n\t\t} else {\n\t\t\tlogger.info(`Starting worker ${process.pid}`)\n\n\t\t\t// this line somehow ensures, that worker waits for termination of all jobs\n\t\t\tprocess.on('disconnect', () => timeout(0))\n\n\t\t\tawait startApplication()\n\t\t\tnotifyWorkerStarted()\n\t\t}\n\t} else {\n\t\tawait startApplication()\n\t\tif (applicationWorker === 'all') {\n\t\t\tfor (const workerName of container.applicationWorkers.getWorkerNames()) {\n\t\t\t\tawait startWorker(workerName)\n\t\t\t}\n\t\t}\n\t\tprintStarted()\n\t}\n\n})().catch(e => {\n\tlogger.crit(e)\n\tprocess.exit(1)\n})\n"],"names":["createDefaultLogger","isDebugMode","getServerVersion","printStartInfo","resolveServerConfig","serverConfigSchema","createSentryLoggerHandler","os","getClusterProcessType","createContainer","listenOnProcessTermination","cluster","notifyWorkerStarted","WorkerManager","timeout"],"mappings":"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"}