From 7af22c9da743573df36a5e2c66ded138edb6ae42 Mon Sep 17 00:00:00 2001 From: "G.Ambatte" Date: Sat, 26 Jul 2025 12:13:59 +1200 Subject: [PATCH] Return a basic error message when DB connection is lost --- server/app.js | 2 + server/middleware/dbCheck.js | 13 +++++++ server/middleware/dbCheck.spec.js | 63 +++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 server/middleware/dbCheck.js create mode 100644 server/middleware/dbCheck.spec.js diff --git a/server/app.js b/server/app.js index 869fe6555..113f4c37d 100644 --- a/server/app.js +++ b/server/app.js @@ -32,6 +32,7 @@ import { splitTextStyleAndMetadata } from '../shared/helpers.js'; //==== Middleware Imports ====// import contentNegotiation from './middleware/content-negotiation.js'; +import dbCheck from './middleware/dbCheck.js'; import bodyParser from 'body-parser'; import cookieParser from 'cookie-parser'; import forceSSL from './forcessl.mw.js'; @@ -49,6 +50,7 @@ const sanitizeBrew = (brew, accessType)=>{ app.set('trust proxy', 1 /* number of proxies between user and server */); app.use('/', serveCompressedStaticAssets(`build`)); +app.use(dbCheck); app.use(contentNegotiation); app.use(bodyParser.json({ limit: '25mb' })); app.use(cookieParser()); diff --git a/server/middleware/dbCheck.js b/server/middleware/dbCheck.js new file mode 100644 index 000000000..e90190517 --- /dev/null +++ b/server/middleware/dbCheck.js @@ -0,0 +1,13 @@ +import mongoose from 'mongoose'; +import config from '../config.js'; + +export default (req, res, next)=>{ + // Bypass DB checks during testing + if(config.get('node_env') == 'test') return next(); + + if(mongoose.connection.readyState == 1) return next(); + return res.status(503).send({ + message : 'Unable to connect to database', + state : mongoose.connection.readyState + }); +}; diff --git a/server/middleware/dbCheck.spec.js b/server/middleware/dbCheck.spec.js new file mode 100644 index 000000000..c4482a54a --- /dev/null +++ b/server/middleware/dbCheck.spec.js @@ -0,0 +1,63 @@ +import mongoose from 'mongoose'; +import dbCheck from './dbCheck.js'; +import config from '../config.js'; + +describe('database check middleware', ()=>{ + let request; + let response; + let next; + + beforeEach(()=>{ + request = { + get : function(key) { + return this[key]; + } + }; + response = { + status : jest.fn(()=>response), + send : jest.fn(()=>{}) + }; + next = jest.fn(); + + // Mock the Config module + jest.mock('../config.js'); + config.get = jest.fn((param)=>{ + // The requested key name will be reflected to the output + return param; + }); + }); + + afterEach(()=>{ + jest.clearAllMocks(); + }); + + it('should return 503 if readystate != 1', ()=>{ + const dbState = mongoose.connection.readyState; + + mongoose.connection.readyState = 99; + + dbCheck(request, response); + + mongoose.connection.readyState = dbState; + + expect(response.status).toHaveBeenLastCalledWith(503); + expect(response.send).toHaveBeenLastCalledWith( + expect.objectContaining({ + message : 'Unable to connect to database', + state : 99 + }) + ); + }); + + it('should call next if readystate == 1', ()=>{ + const dbState = mongoose.connection.readyState; + + mongoose.connection.readyState = 1; + + dbCheck(request, response, next); + + mongoose.connection.readyState = dbState; + + expect(next).toHaveBeenCalled(); + }); +});