diff --git a/keyserver/flow-typed/npm/stoppable_vx.x.x.js b/keyserver/flow-typed/npm/stoppable_vx.x.x.js new file mode 100644 --- /dev/null +++ b/keyserver/flow-typed/npm/stoppable_vx.x.x.js @@ -0,0 +1,28 @@ +// flow-typed signature: 4ffffaa246e31defe6bd7054e7869482 +// flow-typed version: <>/stoppable_v1.1.0/flow_v0.202.1 + +/** + * This is an autogenerated libdef stub for: + * + * 'stoppable' + * + * Fill this stub out by replacing all the `any` types. + * + * Once filled out, we encourage you to share your work with the + * community by sending a pull request to: + * https://github.com/flowtype/flow-typed + */ + +declare module 'stoppable' { + declare module.exports: { + (server: T, grace?: number): T & { + stop(callback?: (error: ?Error, gracefully: boolean) => void): void + } + } +} + +/** + * We include stubs for each file inside this npm package in case you need to + * require those files directly. Feel free to delete any files that aren't + * needed. + */ diff --git a/keyserver/package.json b/keyserver/package.json --- a/keyserver/package.json +++ b/keyserver/package.json @@ -85,6 +85,7 @@ "sharp": "^0.30.5", "siwe": "^2.1.4", "sql-template-strings": "^2.2.2", + "stoppable": "^1.1.0", "tcomb": "^3.2.29", "twin-bcrypt": "^2.1.1", "uuid": "^3.4.0", diff --git a/keyserver/src/keyserver.js b/keyserver/src/keyserver.js --- a/keyserver/src/keyserver.js +++ b/keyserver/src/keyserver.js @@ -11,6 +11,7 @@ import expressWs from 'express-ws'; import os from 'os'; import qrcode from 'qrcode'; +import stoppable from 'stoppable'; import './cron/cron.js'; import { qrCodeLinkURL } from 'lib/facts/links.js'; @@ -95,8 +96,32 @@ const areEndpointMetricsEnabled = process.env.KEYSERVER_ENDPOINT_METRICS_ENABLED; + const listenAddress = (() => { + if (process.env.COMM_LISTEN_ADDR) { + return process.env.COMM_LISTEN_ADDR; + } else if (process.env.NODE_ENV === 'development') { + return undefined; + } else { + return 'localhost'; + } + })(); + if (cluster.isMaster) { if (isPrimaryNode) { + const healthCheckApp = express(); + healthCheckApp.use(express.json({ limit: '250mb' })); + healthCheckApp.get('/health', (req: $Request, res: $Response) => { + res.send('OK'); + }); + + const healthCheckServer = stoppable( + healthCheckApp.listen( + parseInt(process.env.PORT, 10) || 3000, + listenAddress, + ), + 0, + ); + const didMigrationsSucceed: boolean = await migrate(); if (!didMigrationsSucceed) { // The following line uses exit code 2 to ensure nodemon exits @@ -104,6 +129,18 @@ // in https://github.com/remy/nodemon/issues/751 process.exit(2); } + + if (healthCheckServer) { + await new Promise((resolve, reject) => { + healthCheckServer.stop(err => { + if (err) { + reject(err); + } else { + resolve(); + } + }); + }); + } } if (shouldDisplayQRCodeInTerminal && isPrimaryNode) { @@ -317,16 +354,6 @@ }); } - const listenAddress = (() => { - if (process.env.COMM_LISTEN_ADDR) { - return process.env.COMM_LISTEN_ADDR; - } else if (process.env.NODE_ENV === 'development') { - return undefined; - } else { - return 'localhost'; - } - })(); - server.listen(parseInt(process.env.PORT, 10) || 3000, listenAddress); } })(); diff --git a/yarn.lock b/yarn.lock --- a/yarn.lock +++ b/yarn.lock @@ -22492,6 +22492,11 @@ resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" integrity sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g== +stoppable@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/stoppable/-/stoppable-1.1.0.tgz#32da568e83ea488b08e4d7ea2c3bcc9d75015d5b" + integrity sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw== + stopwords-iso@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/stopwords-iso/-/stopwords-iso-1.1.0.tgz#dc303db6b0842d4290bc1339b4eaf37b94219395"