From ef1c15b203ddf85a29571175daba6cea5cb7ae36 Mon Sep 17 00:00:00 2001 From: Luke Bettridge Date: Sat, 21 Mar 2020 16:48:25 +0000 Subject: [PATCH] Introduce Lightship health checks (#57) * Set lightship signal status on mongoose connection * Add unified topology option to mongoose connection * Remove incompatible mongoose options * Register lightship shutdown handler * Update deployment manifest with readiness and liveness probes --- config/deployment.yml | 30 ++++++++-------- package-lock.json | 83 +++++++++++++++++++++++++++++++++++++++---- package.json | 3 +- server/config/db.js | 5 ++- server/index.js | 23 +++++++++--- 5 files changed, 114 insertions(+), 30 deletions(-) diff --git a/config/deployment.yml b/config/deployment.yml index 2cbf2ca..40829e2 100644 --- a/config/deployment.yml +++ b/config/deployment.yml @@ -101,29 +101,29 @@ spec: name: mern-auth-boilerplate-config image: imagePullPolicy: IfNotPresent + readinessProbe: + httpGet: + path: /ready + port: 9000 + failureThreshold: 1 + initialDelaySeconds: 5 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 5 livenessProbe: - failureThreshold: 3 httpGet: - path: / - port: http - scheme: HTTP - periodSeconds: 10 + path: /live + port: 9000 + failureThreshold: 3 + initialDelaySeconds: 5 + periodSeconds: 30 successThreshold: 1 - timeoutSeconds: 1 + timeoutSeconds: 5 name: nodeapp ports: - containerPort: 5000 name: http protocol: TCP - readinessProbe: - failureThreshold: 3 - httpGet: - path: / - port: http - scheme: HTTP - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 resources: {} securityContext: {} terminationMessagePath: /dev/termination-log diff --git a/package-lock.json b/package-lock.json index 6925ea9..fe86636 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3153,6 +3153,11 @@ "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", "dev": true }, + "boolean": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.0.1.tgz", + "integrity": "sha512-HRZPIjPcbwAVQvOTxR4YE3o8Xs98NqbbL1iEZDCz7CL8ql0Lt5iOyJFxfnAB0oFs8Oh02F/lLlg30Mexv46LjA==" + }, "boxen": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz", @@ -4790,6 +4795,11 @@ } } }, + "delay": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/delay/-/delay-4.3.0.tgz", + "integrity": "sha512-Lwaf3zVFDMBop1yDuFZ19F9WyGcZcGacsbdlZtWjQmM50tOcMntm1njF/Nb/Vjij3KaSvCF+sEYGKrrjObu2NA==" + }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -4836,8 +4846,7 @@ "detect-node": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz", - "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==", - "dev": true + "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==" }, "dicer": { "version": "0.3.0", @@ -6527,6 +6536,14 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" }, + "globalthis": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.1.tgz", + "integrity": "sha512-mJPRTc/P39NH/iNG4mXa9aIhNymaQikTrnspeCa2ZuJ+mH2QN/rXwtX3XwKrHqWgUQFbNZKtHM105aHzJalElw==", + "requires": { + "define-properties": "^1.1.3" + } + }, "globby": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", @@ -7142,6 +7159,15 @@ "sshpk": "^1.7.0" } }, + "http-terminator": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/http-terminator/-/http-terminator-2.0.2.tgz", + "integrity": "sha512-Age2I7SNem8pEwbDfL6hhupIn5U9Ro8teZkIZ3/cMyfdk1XqcKFNQFNPYexfhugaCeokRjxzxMM9d+S+G1/rxQ==", + "requires": { + "delay": "^4.3.0", + "roarr": "^2.14.6" + } + }, "https-browserify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", @@ -9087,8 +9113,7 @@ "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, "json3": { "version": "3.3.3", @@ -9256,6 +9281,18 @@ "type-check": "~0.3.2" } }, + "lightship": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/lightship/-/lightship-6.1.0.tgz", + "integrity": "sha512-aWebYfPZJmLBrW1pJK/IVPYY3wwovkj4x0AAUm70vUGQvQpVTN/InZqcnxXwVL/XE6lB0opSoDoqxyEfNVxAfg==", + "requires": { + "delay": "^4.3.0", + "express": "^4.17.1", + "http-terminator": "^2.0.2", + "roarr": "^2.15.2", + "serialize-error": "^5.0.0" + } + }, "lines-and-columns": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", @@ -12314,6 +12351,26 @@ "inherits": "^2.0.1" } }, + "roarr": { + "version": "2.15.2", + "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.2.tgz", + "integrity": "sha512-jmaDhK9CO4YbQAV8zzCnq9vjAqeO489MS5ehZ+rXmFiPFFE6B+S9KYO6prjmLJ5A0zY3QxVlQdrIya7E/azz/Q==", + "requires": { + "boolean": "^3.0.0", + "detect-node": "^2.0.4", + "globalthis": "^1.0.1", + "json-stringify-safe": "^5.0.1", + "semver-compare": "^1.0.0", + "sprintf-js": "^1.1.2" + }, + "dependencies": { + "sprintf-js": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", + "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==" + } + } + }, "rst-selector-parser": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz", @@ -12506,6 +12563,11 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" }, + "semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=" + }, "semver-diff": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz", @@ -12541,6 +12603,14 @@ } } }, + "serialize-error": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-5.0.0.tgz", + "integrity": "sha512-/VtpuyzYf82mHYTtI4QKtwHa79vAdU5OQpNPAmE/0UDdlGT0ZxHwC+J6gXkw29wwoVI8fMPsfcVHOwXtUQYYQA==", + "requires": { + "type-fest": "^0.8.0" + } + }, "serialize-javascript": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz", @@ -13828,8 +13898,7 @@ "type-fest": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==" }, "type-is": { "version": "1.6.18", @@ -16425,4 +16494,4 @@ } } } -} \ No newline at end of file +} diff --git a/package.json b/package.json index 6bdbf55..314364b 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "is-empty": "^1.2.0", "js-cookie": "^2.2.1", "jsonwebtoken": "^8.5.1", + "lightship": "^6.1.0", "lodash": "^4.17.15", "moment": "^2.24.0", "mongoose": "^5.8.6", @@ -103,4 +104,4 @@ "webpack-dev-middleware": "^1.9.0", "webpack-dev-server": "^3.10.1" } -} \ No newline at end of file +} diff --git a/server/config/db.js b/server/config/db.js index 0d3bd87..148bd51 100644 --- a/server/config/db.js +++ b/server/config/db.js @@ -13,8 +13,7 @@ module.exports = { "admin"}${MONGO_REPLICASET ? `&replicaSet=${MONGO_REPLICASET}` : ""}`, options: { connectTimeoutMS: 10000, - reconnectTries: 10, - reconnectInterval: 500, - useNewUrlParser: true + useNewUrlParser: true, + useUnifiedTopology: true } }; diff --git a/server/index.js b/server/index.js index 3031b87..52ef1cf 100644 --- a/server/index.js +++ b/server/index.js @@ -3,6 +3,7 @@ const bodyParser = require("body-parser"); const cookieParser = require("cookie-parser"); const express = require("express"); const mongoose = require("mongoose"); +const { createLightship } = require("lightship"); const { ApolloServer } = require("apollo-server-express"); const router = express.Router(); @@ -19,12 +20,26 @@ const typeDefs = require("./src/types"); const PORT = process.env.PORT || 5000; +const app = express(); + +const lightship = createLightship(); +lightship.registerShutdownHandler(() => { + server.close(); +}); + mongoose .connect(db.url, db.options) - .then(() => console.log("MongoDB successfully connected")) - .catch(err => console.log(err)); - -const app = express(); + .then(() => { + console.log("MongoDB successfully connected"); + mongoose.connection.on("disconnected", () => { + lightship.signalNotReady(); + }); + lightship.signalReady(); + }) + .catch(err => { + console.log(err); + lightship.signalNotReady(); + }); process.env.NODE_ENV !== "production" ? require("./init.dev")(app)