2020-08-25 15:17:11 +00:00
|
|
|
const { StatusCodes } = require("http-status-codes");
|
2020-06-22 09:54:01 +00:00
|
|
|
const { sum, sumBy } = require("lodash");
|
2020-09-09 12:25:00 +00:00
|
|
|
const db = require("../db");
|
2020-06-22 09:54:01 +00:00
|
|
|
|
2020-09-10 10:15:54 +00:00
|
|
|
/**
|
|
|
|
* Get status code that should be returned in the API response.
|
|
|
|
* - OK (200) in case everything is healthy
|
|
|
|
* - SERVICE_UNAVAILABLE (503) in case of any failures or if disabled
|
|
|
|
*/
|
|
|
|
function getStatusCode() {
|
|
|
|
// check whether the portal has been manually disabled
|
|
|
|
const disabled = getDisabled();
|
2020-09-09 12:25:00 +00:00
|
|
|
|
|
|
|
if (disabled) {
|
|
|
|
return StatusCodes.SERVICE_UNAVAILABLE;
|
|
|
|
}
|
|
|
|
|
2020-09-10 11:49:26 +00:00
|
|
|
// grab the most recent critical entry element from DB
|
2020-09-10 12:07:24 +00:00
|
|
|
const entry = getMostRecentCriticalEntry();
|
2020-06-22 09:54:01 +00:00
|
|
|
|
2020-09-10 12:03:56 +00:00
|
|
|
// in case there is no entry yet or at least one check failed in the most recent entry
|
|
|
|
if (!entry || entry.checks.some(({ up }) => !up)) {
|
|
|
|
return StatusCodes.SERVICE_UNAVAILABLE;
|
2020-06-22 09:54:01 +00:00
|
|
|
}
|
|
|
|
|
2020-09-10 12:03:56 +00:00
|
|
|
return StatusCodes.OK;
|
2020-06-22 09:54:01 +00:00
|
|
|
}
|
|
|
|
|
2020-09-10 10:15:54 +00:00
|
|
|
/**
|
|
|
|
* Get the sample of most recent critical entries and
|
2020-09-10 12:05:21 +00:00
|
|
|
* calculate the average response time of all of them
|
2020-09-10 10:15:54 +00:00
|
|
|
*/
|
2020-09-10 12:05:21 +00:00
|
|
|
function getAverageResponseTime() {
|
2020-09-10 10:15:54 +00:00
|
|
|
// get most recent 10 successfull checks for the calculation
|
2020-06-22 09:54:01 +00:00
|
|
|
const sample = db
|
2020-09-10 10:15:54 +00:00
|
|
|
.get("critical")
|
2020-06-22 09:54:01 +00:00
|
|
|
.orderBy("date", "desc")
|
2020-09-10 10:15:54 +00:00
|
|
|
.filter(({ checks }) => checks.every(({ up }) => up))
|
2020-06-22 09:54:01 +00:00
|
|
|
.take(10)
|
|
|
|
.value();
|
|
|
|
|
2020-09-10 12:05:21 +00:00
|
|
|
// calculate average time of response
|
2020-06-22 09:54:01 +00:00
|
|
|
return Math.round(sum(sample.map(({ checks }) => sumBy(checks, "time"))) / sample.size);
|
|
|
|
}
|
|
|
|
|
2020-09-10 10:15:54 +00:00
|
|
|
/**
|
|
|
|
* Get one, most current critical entry
|
|
|
|
*/
|
2020-09-10 12:07:24 +00:00
|
|
|
function getMostRecentCriticalEntry() {
|
2020-09-10 10:15:54 +00:00
|
|
|
return db.get("critical").orderBy("date", "desc").head().value();
|
|
|
|
}
|
2020-06-22 09:54:01 +00:00
|
|
|
|
2020-09-10 10:15:54 +00:00
|
|
|
/**
|
|
|
|
* Get the disabled flag state (manual portal disable)
|
|
|
|
*/
|
|
|
|
function getDisabled() {
|
|
|
|
return db.get("disabled").value();
|
2020-06-22 09:54:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = (req, res) => {
|
2020-09-10 10:15:54 +00:00
|
|
|
const statusCode = getStatusCode();
|
2020-09-10 12:05:21 +00:00
|
|
|
const timeout = statusCode === StatusCodes.OK ? getAverageResponseTime() : 0;
|
2020-09-10 10:15:54 +00:00
|
|
|
|
|
|
|
// We want to delay the response for the load balancer to be able to prioritize
|
2020-09-10 11:49:26 +00:00
|
|
|
// servers based on the successful response time of this endpoint. Load balancer
|
2020-09-10 10:15:54 +00:00
|
|
|
// will pull the server if the response is an error so there is no point in delaying
|
|
|
|
// failures, hence 0 timeout on those.
|
2020-06-22 09:54:01 +00:00
|
|
|
setTimeout(() => {
|
2020-09-10 10:15:54 +00:00
|
|
|
// include some health information in the response body
|
2020-09-10 12:07:24 +00:00
|
|
|
const entry = getMostRecentCriticalEntry();
|
2020-09-10 10:15:54 +00:00
|
|
|
const disabled = getDisabled();
|
|
|
|
|
|
|
|
res.status(statusCode).send({ disabled, entry });
|
|
|
|
}, timeout);
|
2020-06-22 09:54:01 +00:00
|
|
|
};
|