This repository has been archived on 2022-10-07. You can view files and clone it, but cannot push or open issues or pull requests.
skynet-webportal/packages/health-check/src/api/index.js

76 lines
2.2 KiB
JavaScript

const { StatusCodes } = require("http-status-codes");
const { sum, sumBy } = require("lodash");
const db = require("../db");
/**
* 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();
if (disabled) {
return StatusCodes.SERVICE_UNAVAILABLE;
}
// grab the most recent critical entry element from DB
const entry = getMostRecentCriticalEntry();
// 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;
}
return StatusCodes.OK;
}
/**
* Get the sample of most recent critical entries and
* calculate the average response time of all of them
*/
function getAverageResponseTime() {
// get most recent 10 successfull checks for the calculation
const sample = db
.get("critical")
.orderBy("date", "desc")
.filter(({ checks }) => checks.every(({ up }) => up))
.take(10)
.value();
// calculate average time of response
return Math.round(sum(sample.map(({ checks }) => sumBy(checks, "time"))) / sample.size);
}
/**
* Get one, most current critical entry
*/
function getMostRecentCriticalEntry() {
return db.get("critical").orderBy("date", "desc").head().value();
}
/**
* Get the disabled flag state (manual portal disable)
*/
function getDisabled() {
return db.get("disabled").value();
}
module.exports = (req, res) => {
const statusCode = getStatusCode();
const timeout = statusCode === StatusCodes.OK ? getAverageResponseTime() : 0;
// We want to delay the response for the load balancer to be able to prioritize
// servers based on the successful response time of this endpoint. Load balancer
// will pull the server if the response is an error so there is no point in delaying
// failures, hence 0 timeout on those.
setTimeout(() => {
// include some health information in the response body
const entry = getMostRecentCriticalEntry();
const disabled = getDisabled();
res.status(statusCode).send({ disabled, entry });
}, timeout);
};