зеркало из https://github.com/mozilla/CSOL-site.git
133 строки
3.6 KiB
JavaScript
133 строки
3.6 KiB
JavaScript
// TODO: Separate this module out into its own npm module/git repo.
|
|
|
|
var async = require('async');
|
|
var colors = require('colors');
|
|
|
|
const CHECKMARK = "\u2713";
|
|
|
|
function checker(fn) {
|
|
var meta = {};
|
|
var result = function(obj) {
|
|
Object.keys(obj).forEach(function(prop) {
|
|
meta[prop] = obj[prop];
|
|
});
|
|
return meta;
|
|
};
|
|
|
|
return function check(cb) {
|
|
var timeout = setTimeout(function() {
|
|
timeout = null;
|
|
cb(null, result({status: "FAILED", reason: "TIMEOUT"}));
|
|
}, module.exports.TIMEOUT);
|
|
|
|
try {
|
|
fn(meta, function(err) {
|
|
if (timeout === null) return;
|
|
clearTimeout(timeout);
|
|
timeout = null;
|
|
if (err)
|
|
return cb(null, result({
|
|
status: "FAILED",
|
|
reason: err.toString()
|
|
}));
|
|
cb(null, result({status: "OK"}));
|
|
});
|
|
} catch (e) {
|
|
clearTimeout(timeout);
|
|
timeout = null;
|
|
cb(null, result({status: "FAILED", reason: e.toString()}));
|
|
}
|
|
};
|
|
}
|
|
|
|
function sessionStorageChecker(sessionStore) {
|
|
return checker(function checkSessionStorage(meta, cb) {
|
|
var randomNumber = Math.floor(Math.random() * 10000000);
|
|
var sid = "healthCheck_sessionStorage_" + randomNumber;
|
|
var session = {
|
|
n: randomNumber,
|
|
cookie: {maxAge: 3600}
|
|
};
|
|
|
|
async.series([
|
|
sessionStore.set.bind(sessionStore, sid, session),
|
|
function(cb) {
|
|
sessionStore.get(sid, function(err, val) {
|
|
if (err) return cb(err);
|
|
if (!(val && val.n == randomNumber))
|
|
return cb(new Error("session store read/write failure"));
|
|
cb();
|
|
});
|
|
},
|
|
sessionStore.destroy.bind(sessionStore, sid)
|
|
], cb);
|
|
});
|
|
}
|
|
|
|
function runChecks(checks, cb) {
|
|
async.parallel(checks, function(err, results) {
|
|
if (err !== null)
|
|
// This should never happen b/c checkers should catch all errors.
|
|
return cb({
|
|
status: "FAILED",
|
|
reason: "a checker threw an error: " + err
|
|
});
|
|
|
|
Object.keys(results).forEach(function(checkName) {
|
|
if (results[checkName].status != "OK")
|
|
results.status = "FAILED";
|
|
});
|
|
if (results.status != "FAILED")
|
|
results.status = "OK";
|
|
cb(results);
|
|
});
|
|
}
|
|
|
|
function resultsToConsoleString(results) {
|
|
var lines = [];
|
|
|
|
Object.keys(results).forEach(function(name) {
|
|
var info = results[name];
|
|
|
|
if (info && typeof(info) == "object" && info.status) {
|
|
var fullName = name;
|
|
if (info.notes) fullName += " (" + info.notes + ")";
|
|
if (info.status == "OK") {
|
|
lines.push(CHECKMARK.green + " " + fullName.grey);
|
|
} else {
|
|
lines.push("x".red + " " + fullName.grey + " " +
|
|
(info.reason ? info.reason : ""));
|
|
}
|
|
}
|
|
});
|
|
|
|
return lines.join('\n');
|
|
}
|
|
|
|
module.exports = function healthCheck(options) {
|
|
var authenticate = options.auth || function(req, res, next) { next(); };
|
|
var checks = options.checks;
|
|
|
|
var healthChecker = function healthChecker(req, res, next) {
|
|
if (req.query['elb'] == 'true')
|
|
return res.send(200, {status: "OK"});
|
|
|
|
authenticate(req, res, function(err) {
|
|
if (err) return next(err);
|
|
|
|
runChecks(checks, function(results) {
|
|
var statusCode = results.status == "OK" ? 200 : 500;
|
|
return res.json(statusCode, results);
|
|
});
|
|
});
|
|
};
|
|
healthChecker.runChecks = runChecks.bind(null, checks);
|
|
return healthChecker;
|
|
};
|
|
|
|
module.exports.TIMEOUT = 15000;
|
|
module.exports.resultsToConsoleString = resultsToConsoleString;
|
|
module.exports.runChecks = runChecks;
|
|
module.exports.sessionStorageChecker = sessionStorageChecker;
|
|
module.exports.checker = checker;
|