diff --git a/Dockerfile b/Dockerfile index 0b6ab6e45a..9c99a9da29 100644 --- a/Dockerfile +++ b/Dockerfile @@ -84,4 +84,4 @@ COPY --chown=cherrypick:cherrypick . ./ ENV NODE_ENV=production HEALTHCHECK --interval=5s --retries=20 CMD ["/bin/bash", "/cherrypick/healthcheck.sh"] ENTRYPOINT ["/usr/bin/tini", "--"] -CMD ["pnpm", "run", "migrateandstart"] +CMD ["pnpm", "run", "migrateandstart:docker"] diff --git a/package.json b/package.json index e408f1198f..2012e7a13e 100644 --- a/package.json +++ b/package.json @@ -18,11 +18,13 @@ "build": "pnpm build-pre && pnpm -r build && pnpm gulp", "build-storybook": "pnpm --filter frontend build-storybook", "start": "pnpm check:connect && cd packages/backend && node ./built/boot/index.js", + "start:docker": "pnpm check:connect && cd packages/backend && exec node ./built/boot/index.js", "start:test": "cd packages/backend && cross-env NODE_ENV=test node ./built/boot/index.js", "init": "pnpm migrate", "migrate": "cd packages/backend && pnpm migrate", "check:connect": "cd packages/backend && pnpm check:connect", "migrateandstart": "pnpm migrate && pnpm start", + "migrateandstart:docker": "pnpm migrate && exec pnpm start:docker", "gulp": "pnpm exec gulp build", "watch": "pnpm dev", "dev": "node ./scripts/dev.mjs", diff --git a/packages/backend/src/boot/index.ts b/packages/backend/src/boot/index.ts index 9e265ba9df..3b427d204e 100644 --- a/packages/backend/src/boot/index.ts +++ b/packages/backend/src/boot/index.ts @@ -29,23 +29,39 @@ const ev = new Xev(); //#region Events -// Listen new workers -cluster.on('fork', worker => { - clusterLogger.debug(`Process forked: [${worker.id}]`); -}); +if (cluster.isPrimary && !envOption.disableClustering) { + // Listen new workers + cluster.on('fork', worker => { + clusterLogger.debug(`Process forked: [${worker.id}]`); + }); -// Listen online workers -cluster.on('online', worker => { - clusterLogger.debug(`Process is now online: [${worker.id}]`); -}); + // Listen online workers + cluster.on('online', worker => { + clusterLogger.debug(`Process is now online: [${worker.id}]`); + }); -// Listen for dying workers -cluster.on('exit', worker => { - // Replace the dead worker, - // we're not sentimental - clusterLogger.error(chalk.red(`[${worker.id}] died :(`)); - cluster.fork(); -}); + // Listen for dying workers + cluster.on('exit', (worker, code, signal?) => { + // Replace the dead worker, + // we're not sentimental + if (signal) { + switch (signal) { + case 'SIGINT': + case 'SIGTERM': + console.log(chalk.green(`[${worker.id}] exited by signal: ${signal}`)); + break; + default: + console.error(chalk.red(`[${worker.id}] killed by signal: ${signal}`)); + cluster.fork(); + break; + } + } else if (code !== 0) { + console.error(chalk.red(`[${worker.id}] exited with error code: ${code}`)); + } else { + console.log(chalk.green(`[${worker.id}] exited normally`)); + } + }); +} // Display detail of unhandled promise rejection if (!envOption.quiet) { diff --git a/packages/backend/src/server/ServerService.ts b/packages/backend/src/server/ServerService.ts index 2b7581c444..a86b22abf3 100644 --- a/packages/backend/src/server/ServerService.ts +++ b/packages/backend/src/server/ServerService.ts @@ -250,7 +250,7 @@ export class ServerService implements OnApplicationShutdown { @bindThis public async dispose(): Promise { - await this.streamingApiServerService.detach(); + this.streamingApiServerService.detach(); await this.#fastify.close(); } diff --git a/packages/backend/src/server/api/StreamingApiServerService.ts b/packages/backend/src/server/api/StreamingApiServerService.ts index 33af842766..1674b1a93b 100644 --- a/packages/backend/src/server/api/StreamingApiServerService.ts +++ b/packages/backend/src/server/api/StreamingApiServerService.ts @@ -168,13 +168,12 @@ export class StreamingApiServerService { } @bindThis - public detach(): Promise { + public detach(): void { if (this.#cleanConnectionsIntervalId) { clearInterval(this.#cleanConnectionsIntervalId); this.#cleanConnectionsIntervalId = null; } - return new Promise((resolve) => { - this.#wss.close(() => resolve()); - }); + this.#wss.close(); + this.#wss.clients.forEach(client => client.terminate()); } }