Files
overleaf-cep/services/web/app/src/Features/HealthCheck/HealthCheckController.js
Alf Eaton 1ebc8a79cb Merge pull request #3495 from overleaf/ae-prettier-2
Upgrade Prettier to v2

GitOrigin-RevId: 85aa3fa1acb6332c4f58c46165a43d1a51471f33
2021-04-15 02:05:22 +00:00

126 lines
3.6 KiB
JavaScript

const RedisWrapper = require('../../infrastructure/RedisWrapper')
const rclient = RedisWrapper.client('health_check')
const settings = require('settings-sharelatex')
const logger = require('logger-sharelatex')
const UserGetter = require('../User/UserGetter')
const {
SmokeTestFailure,
runSmokeTests
} = require('./../../../../test/smoke/src/SmokeTests')
module.exports = {
check(req, res, next) {
if (!settings.siteIsOpen || !settings.editorIsOpen) {
// always return successful health checks when site is closed
res.contentType('application/json')
res.sendStatus(200)
} else {
// detach from express for cleaner stack traces
setTimeout(() => runSmokeTestsDetached(req, res).catch(next))
}
},
checkActiveHandles(req, res, next) {
if (!(settings.maxActiveHandles > 0) || !process._getActiveHandles) {
return next()
}
const activeHandlesCount = (process._getActiveHandles() || []).length
if (activeHandlesCount > settings.maxActiveHandles) {
logger.err(
{ activeHandlesCount, maxActiveHandles: settings.maxActiveHandles },
'exceeded max active handles, failing health check'
)
return res.sendStatus(500)
} else {
logger.debug(
{ activeHandlesCount, maxActiveHandles: settings.maxActiveHandles },
'active handles are below maximum'
)
next()
}
},
checkApi(req, res, next) {
rclient.healthCheck(err => {
if (err) {
logger.err({ err }, 'failed api redis health check')
return res.sendStatus(500)
}
UserGetter.getUserEmail(settings.smokeTest.userId, (err, email) => {
if (err) {
logger.err({ err }, 'failed api mongo health check')
return res.sendStatus(500)
}
if (email == null) {
logger.err({ err }, 'failed api mongo health check (no email)')
return res.sendStatus(500)
}
res.sendStatus(200)
})
})
},
checkRedis(req, res, next) {
return rclient.healthCheck(function (error) {
if (error != null) {
logger.err({ err: error }, 'failed redis health check')
return res.sendStatus(500)
} else {
return res.sendStatus(200)
}
})
},
checkMongo(req, res, next) {
return UserGetter.getUserEmail(
settings.smokeTest.userId,
function (err, email) {
if (err != null) {
logger.err({ err }, 'mongo health check failed, error present')
return res.sendStatus(500)
} else if (email == null) {
logger.err(
{ err },
'mongo health check failed, no emai present in find result'
)
return res.sendStatus(500)
} else {
return res.sendStatus(200)
}
}
)
}
}
function prettyJSON(blob) {
return JSON.stringify(blob, null, 2) + '\n'
}
async function runSmokeTestsDetached(req, res) {
function isAborted() {
return req.aborted
}
const stats = { start: new Date(), steps: [] }
let status, response
try {
try {
await runSmokeTests({ isAborted, stats })
} finally {
stats.end = new Date()
stats.duration = stats.end - stats.start
}
status = 200
response = { stats }
} catch (e) {
let err = e
if (!(e instanceof SmokeTestFailure)) {
err = new SmokeTestFailure('low level error', {}, e)
}
logger.err({ err, stats }, 'health check failed')
status = 500
response = { stats, error: err.message }
}
if (isAborted()) return
res.contentType('application/json')
res.status(status).send(prettyJSON(response))
}