From b8cd6aa13931949a3d2c6ec5a6ff25343d1bb015 Mon Sep 17 00:00:00 2001 From: Aditya Pandey Date: Mon, 14 Oct 2024 10:55:41 -0500 Subject: [PATCH] Properly kill dev api-server (#11691) Changes are: - await the process where we kill the server process when restarting. So that we don't race the new instance of httpServer with existing ones (while being killed). - try to gracefully kill the api server, if it's not killed within 2sec, SIGTERM it. - unrelated: moved a comment to the right place. I accidentally moved it wrong place while refactoring in the last PR. --- .changesets/11691.md | 3 +++ packages/api-server/src/buildManager.ts | 10 ++++---- packages/api-server/src/serverManager.ts | 31 +++++++++++++++++++++--- 3 files changed, 35 insertions(+), 9 deletions(-) create mode 100644 .changesets/11691.md diff --git a/.changesets/11691.md b/.changesets/11691.md new file mode 100644 index 000000000000..94b9bf921c41 --- /dev/null +++ b/.changesets/11691.md @@ -0,0 +1,3 @@ +- Await and properly kill dev api-server (#11691) by @callingmedic911 + +Sometime the api-server doesn't get killed in time before the new instance is started. This change makes sure that we wait for the process. If it's not killed within 2 seconds with SIGTERM, we send a SIGKILL to it. diff --git a/packages/api-server/src/buildManager.ts b/packages/api-server/src/buildManager.ts index bc53b679eb2a..8ebdecdeeea8 100644 --- a/packages/api-server/src/buildManager.ts +++ b/packages/api-server/src/buildManager.ts @@ -5,11 +5,6 @@ export type BuildAndRestartOptions = { clean?: boolean } -// We want to delay execution when multiple files are modified on the filesystem, -// this usually happens when running RedwoodJS generator commands. -// Local writes are very fast, but writes in e2e environments are not, -// so allow the default to be adjusted with an env-var. -// class BuildManager { private shouldRebuild: boolean private shouldClean: boolean @@ -34,6 +29,11 @@ class BuildManager { this.shouldClean = false } }, + // We want to delay execution when multiple files are modified on the filesystem, + // this usually happens when running RedwoodJS generator commands. + // Local writes are very fast, but writes in e2e environments are not, + // so allow the default to be adjusted with an env-var. + // process.env.RWJS_DELAY_RESTART ? parseInt(process.env.RWJS_DELAY_RESTART, 10) : 500, diff --git a/packages/api-server/src/serverManager.ts b/packages/api-server/src/serverManager.ts index 526c303b3ed4..4027255bcee1 100644 --- a/packages/api-server/src/serverManager.ts +++ b/packages/api-server/src/serverManager.ts @@ -3,6 +3,7 @@ import { fork } from 'child_process' import fs from 'fs' import path from 'path' +import chalk from 'chalk' import yargs from 'yargs' import { hideBin } from 'yargs/helpers' @@ -82,13 +83,35 @@ export class ServerManager { } async restartApiServer() { - this.killApiServer() + await this.killApiServer() await this.startApiServer() } - killApiServer() { - this.httpServerProcess?.emit('exit') - this.httpServerProcess?.kill() + async killApiServer() { + if (!this.httpServerProcess) { + return + } + + // Try to gracefully close the server + // If it doesn't close within 2 seconds, forcefully close it + await Promise.race([ + new Promise((resolve) => { + console.log(chalk.yellow('Shutting down API server.')) + this.httpServerProcess!.on('exit', () => resolve()) + this.httpServerProcess!.kill() + }), + new Promise((resolve) => + setTimeout(() => { + console.log( + chalk.yellow( + 'API server did not exit within 2 seconds, forcefully closing it.', + ), + ) + this.httpServerProcess!.kill('SIGKILL') + resolve() + }, 2000), + ), + ]) } }