mirror of
https://github.com/louislam/uptime-kuma.git
synced 2025-06-03 12:02:33 +02:00

Reformatted code across multiple modules, standardizing string quotes, indentation, and spacing. Improved readability by restructuring blocks and aligning object properties consistently. These changes ensure better code maintainability and follow standard conventions. Signed-off-by: Toby Liddicoat <toby@codesure.co.uk>
639 lines
23 KiB
JavaScript
639 lines
23 KiB
JavaScript
let express = require("express");
|
|
const {
|
|
setting,
|
|
allowDevAllOrigin,
|
|
allowAllOrigin,
|
|
percentageToColor,
|
|
filterAndJoin,
|
|
sendHttpError,
|
|
} = require("../util-server");
|
|
const { R } = require("redbean-node");
|
|
const apicache = require("../modules/apicache");
|
|
const Monitor = require("../model/monitor");
|
|
const dayjs = require("dayjs");
|
|
const {
|
|
UP,
|
|
MAINTENANCE,
|
|
DOWN,
|
|
PENDING,
|
|
flipStatus,
|
|
log,
|
|
badgeConstants,
|
|
} = require("../../src/util");
|
|
const StatusPage = require("../model/status_page");
|
|
const { UptimeKumaServer } = require("../uptime-kuma-server");
|
|
const { makeBadge } = require("badge-maker");
|
|
const { Prometheus } = require("../prometheus");
|
|
const Database = require("../database");
|
|
const { UptimeCalculator } = require("../uptime-calculator");
|
|
|
|
let router = express.Router();
|
|
|
|
let cache = apicache.middleware;
|
|
const server = UptimeKumaServer.getInstance();
|
|
let io = server.io;
|
|
|
|
router.get("/api/entry-page", async (request, response) => {
|
|
allowDevAllOrigin(response);
|
|
|
|
let result = {};
|
|
let hostname = request.hostname;
|
|
if ((await setting("trustProxy")) && request.headers["x-forwarded-host"]) {
|
|
hostname = request.headers["x-forwarded-host"];
|
|
}
|
|
|
|
if (hostname in StatusPage.domainMappingList) {
|
|
result.type = "statusPageMatchedDomain";
|
|
result.statusPageSlug = StatusPage.domainMappingList[hostname];
|
|
} else {
|
|
result.type = "entryPage";
|
|
result.entryPage = server.entryPage;
|
|
}
|
|
response.json(result);
|
|
});
|
|
|
|
router.all("/api/push/:pushToken", async (request, response) => {
|
|
try {
|
|
let pushToken = request.params.pushToken;
|
|
let msg = request.query.msg || "OK";
|
|
let ping = parseFloat(request.query.ping) || null;
|
|
let statusString = request.query.status || "up";
|
|
let status = (statusString === "up") ? UP : DOWN;
|
|
|
|
let monitor = await R.findOne("monitor", " push_token = ? AND active = 1 ", [
|
|
pushToken,
|
|
]);
|
|
|
|
if (!monitor) {
|
|
throw new Error("Monitor not found or not active.");
|
|
}
|
|
|
|
const previousHeartbeat = await Monitor.getPreviousHeartbeat(monitor.id);
|
|
|
|
let isFirstBeat = true;
|
|
|
|
let bean = R.dispense("heartbeat");
|
|
bean.time = R.isoDateTimeMillis(dayjs.utc());
|
|
bean.monitor_id = monitor.id;
|
|
bean.ping = ping;
|
|
bean.msg = msg;
|
|
bean.downCount = previousHeartbeat?.downCount || 0;
|
|
|
|
if (previousHeartbeat) {
|
|
isFirstBeat = false;
|
|
bean.duration = dayjs(bean.time).diff(dayjs(previousHeartbeat.time), "second");
|
|
}
|
|
|
|
if (await Monitor.isUnderMaintenance(monitor.id)) {
|
|
msg = "Monitor under maintenance";
|
|
bean.status = MAINTENANCE;
|
|
} else {
|
|
determineStatus(status, previousHeartbeat, monitor.maxretries, monitor.isUpsideDown(), bean);
|
|
}
|
|
|
|
// Calculate uptime
|
|
let uptimeCalculator = await UptimeCalculator.getUptimeCalculator(monitor.id);
|
|
let endTimeDayjs = await uptimeCalculator.update(bean.status, parseFloat(bean.ping));
|
|
bean.end_time = R.isoDateTimeMillis(endTimeDayjs);
|
|
|
|
log.debug("router", `/api/push/ called at ${dayjs().format("YYYY-MM-DD HH:mm:ss.SSS")}`);
|
|
log.debug("router", "PreviousStatus: " + previousHeartbeat?.status);
|
|
log.debug("router", "Current Status: " + bean.status);
|
|
|
|
bean.important = Monitor.isImportantBeat(isFirstBeat, previousHeartbeat?.status, status);
|
|
|
|
if (Monitor.isImportantForNotification(isFirstBeat, previousHeartbeat?.status, status)) {
|
|
// Reset down count
|
|
bean.downCount = 0;
|
|
|
|
log.debug("monitor", `[${this.name}] sendNotification`);
|
|
await Monitor.sendNotification(isFirstBeat, monitor, bean);
|
|
} else {
|
|
if (bean.status === DOWN && this.resendInterval > 0) {
|
|
++bean.downCount;
|
|
if (bean.downCount >= this.resendInterval) {
|
|
// Send notification again, because we are still DOWN
|
|
log.debug("monitor", `[${this.name}] sendNotification again: Down Count: ${bean.downCount} | Resend Interval: ${this.resendInterval}`);
|
|
await Monitor.sendNotification(isFirstBeat, this, bean);
|
|
|
|
// Reset down count
|
|
bean.downCount = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
await R.store(bean);
|
|
|
|
io.to(monitor.user_id).emit("heartbeat", bean.toJSON());
|
|
|
|
Monitor.sendStats(io, monitor.id, monitor.user_id);
|
|
new Prometheus(monitor).update(bean, undefined);
|
|
|
|
response.json({
|
|
ok: true,
|
|
});
|
|
} catch (e) {
|
|
response.status(404).json({
|
|
ok: false,
|
|
msg: e.message,
|
|
});
|
|
}
|
|
});
|
|
|
|
router.get("/api/badge/:id/status", cache("5 minutes"), async (request, response) => {
|
|
allowAllOrigin(response);
|
|
|
|
const {
|
|
label,
|
|
upLabel = "Up",
|
|
downLabel = "Down",
|
|
pendingLabel = "Pending",
|
|
maintenanceLabel = "Maintenance",
|
|
upColor = badgeConstants.defaultUpColor,
|
|
downColor = badgeConstants.defaultDownColor,
|
|
pendingColor = badgeConstants.defaultPendingColor,
|
|
maintenanceColor = badgeConstants.defaultMaintenanceColor,
|
|
style = badgeConstants.defaultStyle,
|
|
value, // for demo purpose only
|
|
} = request.query;
|
|
|
|
try {
|
|
const requestedMonitorId = parseInt(request.params.id, 10);
|
|
const overrideValue = value !== undefined ? parseInt(value) : undefined;
|
|
|
|
let publicMonitor = await R.getRow(`
|
|
SELECT monitor_group.monitor_id FROM monitor_group, \`group\`
|
|
WHERE monitor_group.group_id = \`group\`.id
|
|
AND monitor_group.monitor_id = ?
|
|
AND public = 1
|
|
`,
|
|
[ requestedMonitorId ],
|
|
);
|
|
|
|
const badgeValues = { style };
|
|
|
|
if (!publicMonitor) {
|
|
// return a "N/A" badge in naColor (grey), if monitor is not public / not available / non exsitant
|
|
|
|
badgeValues.message = "N/A";
|
|
badgeValues.color = badgeConstants.naColor;
|
|
} else {
|
|
const heartbeat = await Monitor.getPreviousHeartbeat(requestedMonitorId);
|
|
const state = overrideValue !== undefined ? overrideValue : heartbeat.status;
|
|
|
|
if (label === undefined) {
|
|
badgeValues.label = "Status";
|
|
} else {
|
|
badgeValues.label = label;
|
|
}
|
|
switch (state) {
|
|
case DOWN:
|
|
badgeValues.color = downColor;
|
|
badgeValues.message = downLabel;
|
|
break;
|
|
case UP:
|
|
badgeValues.color = upColor;
|
|
badgeValues.message = upLabel;
|
|
break;
|
|
case PENDING:
|
|
badgeValues.color = pendingColor;
|
|
badgeValues.message = pendingLabel;
|
|
break;
|
|
case MAINTENANCE:
|
|
badgeValues.color = maintenanceColor;
|
|
badgeValues.message = maintenanceLabel;
|
|
break;
|
|
default:
|
|
badgeValues.color = badgeConstants.naColor;
|
|
badgeValues.message = "N/A";
|
|
}
|
|
}
|
|
|
|
// build the svg based on given values
|
|
const svg = makeBadge(badgeValues);
|
|
|
|
response.type("image/svg+xml");
|
|
response.send(svg);
|
|
} catch (error) {
|
|
sendHttpError(response, error.message);
|
|
}
|
|
});
|
|
|
|
router.get("/api/badge/:id/uptime/:duration?", cache("5 minutes"), async (request, response) => {
|
|
allowAllOrigin(response);
|
|
|
|
const {
|
|
label,
|
|
labelPrefix,
|
|
labelSuffix = badgeConstants.defaultUptimeLabelSuffix,
|
|
prefix,
|
|
suffix = badgeConstants.defaultUptimeValueSuffix,
|
|
color,
|
|
labelColor,
|
|
style = badgeConstants.defaultStyle,
|
|
value, // for demo purpose only
|
|
} = request.query;
|
|
|
|
try {
|
|
const requestedMonitorId = parseInt(request.params.id, 10);
|
|
// if no duration is given, set value to 24 (h)
|
|
let requestedDuration = request.params.duration !== undefined ? request.params.duration : "24h";
|
|
const overrideValue = value && parseFloat(value);
|
|
|
|
if (/^[0-9]+$/.test(requestedDuration)) {
|
|
requestedDuration = `${requestedDuration}h`;
|
|
}
|
|
|
|
let publicMonitor = await R.getRow(`
|
|
SELECT monitor_group.monitor_id FROM monitor_group, \`group\`
|
|
WHERE monitor_group.group_id = \`group\`.id
|
|
AND monitor_group.monitor_id = ?
|
|
AND public = 1
|
|
`,
|
|
[ requestedMonitorId ],
|
|
);
|
|
|
|
const badgeValues = { style };
|
|
|
|
if (!publicMonitor) {
|
|
// return a "N/A" badge in naColor (grey), if monitor is not public / not available / non existent
|
|
badgeValues.message = "N/A";
|
|
badgeValues.color = badgeConstants.naColor;
|
|
} else {
|
|
const uptimeCalculator = await UptimeCalculator.getUptimeCalculator(requestedMonitorId);
|
|
const uptime = overrideValue ?? uptimeCalculator.getDataByDuration(requestedDuration).uptime;
|
|
|
|
// limit the displayed uptime percentage to four (two, when displayed as percent) decimal digits
|
|
const cleanUptime = (uptime * 100).toPrecision(4);
|
|
|
|
// use a given, custom color or calculate one based on the uptime value
|
|
badgeValues.color = color ?? percentageToColor(uptime);
|
|
// use a given, custom labelColor or use the default badge label color (defined by badge-maker)
|
|
badgeValues.labelColor = labelColor ?? "";
|
|
// build a label string. If a custom label is given, override the default one (requestedDuration)
|
|
badgeValues.label = filterAndJoin([
|
|
labelPrefix,
|
|
label ?? `Uptime (${requestedDuration.slice(0, -1)}${labelSuffix})`,
|
|
]);
|
|
badgeValues.message = filterAndJoin([ prefix, cleanUptime, suffix ]);
|
|
}
|
|
|
|
// build the SVG based on given values
|
|
const svg = makeBadge(badgeValues);
|
|
|
|
response.type("image/svg+xml");
|
|
response.send(svg);
|
|
} catch (error) {
|
|
sendHttpError(response, error.message);
|
|
}
|
|
});
|
|
|
|
router.get("/api/badge/:id/ping/:duration?", cache("5 minutes"), async (request, response) => {
|
|
allowAllOrigin(response);
|
|
|
|
const {
|
|
label,
|
|
labelPrefix,
|
|
labelSuffix = badgeConstants.defaultPingLabelSuffix,
|
|
prefix,
|
|
suffix = badgeConstants.defaultPingValueSuffix,
|
|
color = badgeConstants.defaultPingColor,
|
|
labelColor,
|
|
style = badgeConstants.defaultStyle,
|
|
value, // for demo purpose only
|
|
} = request.query;
|
|
|
|
try {
|
|
const requestedMonitorId = parseInt(request.params.id, 10);
|
|
|
|
// Default duration is 24 (h) if not defined in queryParam, limited to 720h (30d)
|
|
let requestedDuration = request.params.duration !== undefined ? request.params.duration : "24h";
|
|
const overrideValue = value && parseFloat(value);
|
|
|
|
if (/^[0-9]+$/.test(requestedDuration)) {
|
|
requestedDuration = `${requestedDuration}h`;
|
|
}
|
|
|
|
// Check if monitor is public
|
|
|
|
const uptimeCalculator = await UptimeCalculator.getUptimeCalculator(requestedMonitorId);
|
|
const publicAvgPing = uptimeCalculator.getDataByDuration(requestedDuration).avgPing;
|
|
|
|
const badgeValues = { style };
|
|
|
|
if (!publicAvgPing) {
|
|
// return a "N/A" badge in naColor (grey), if monitor is not public / not available / non exsitant
|
|
|
|
badgeValues.message = "N/A";
|
|
badgeValues.color = badgeConstants.naColor;
|
|
} else {
|
|
const avgPing = parseInt(overrideValue ?? publicAvgPing);
|
|
|
|
badgeValues.color = color;
|
|
// use a given, custom labelColor or use the default badge label color (defined by badge-maker)
|
|
badgeValues.labelColor = labelColor ?? "";
|
|
// build a lable string. If a custom label is given, override the default one (requestedDuration)
|
|
badgeValues.label = filterAndJoin([ labelPrefix, label ?? `Avg. Ping (${requestedDuration.slice(0, -1)}${labelSuffix})` ]);
|
|
badgeValues.message = filterAndJoin([ prefix, avgPing, suffix ]);
|
|
}
|
|
|
|
// build the SVG based on given values
|
|
const svg = makeBadge(badgeValues);
|
|
|
|
response.type("image/svg+xml");
|
|
response.send(svg);
|
|
} catch (error) {
|
|
sendHttpError(response, error.message);
|
|
}
|
|
});
|
|
|
|
router.get("/api/badge/:id/avg-response/:duration?", cache("5 minutes"), async (request, response) => {
|
|
allowAllOrigin(response);
|
|
|
|
const {
|
|
label,
|
|
labelPrefix,
|
|
labelSuffix,
|
|
prefix,
|
|
suffix = badgeConstants.defaultPingValueSuffix,
|
|
color = badgeConstants.defaultPingColor,
|
|
labelColor,
|
|
style = badgeConstants.defaultStyle,
|
|
value, // for demo purpose only
|
|
} = request.query;
|
|
|
|
try {
|
|
const requestedMonitorId = parseInt(request.params.id, 10);
|
|
|
|
// Default duration is 24 (h) if not defined in queryParam, limited to 720h (30d)
|
|
const requestedDuration = Math.min(
|
|
request.params.duration
|
|
? parseInt(request.params.duration, 10)
|
|
: 24,
|
|
720,
|
|
);
|
|
const overrideValue = value && parseFloat(value);
|
|
|
|
const sqlHourOffset = Database.sqlHourOffset();
|
|
|
|
const publicAvgPing = parseInt(await R.getCell(`
|
|
SELECT AVG(ping) FROM monitor_group, \`group\`, heartbeat
|
|
WHERE monitor_group.group_id = \`group\`.id
|
|
AND heartbeat.time > ${sqlHourOffset}
|
|
AND heartbeat.ping IS NOT NULL
|
|
AND public = 1
|
|
AND heartbeat.monitor_id = ?
|
|
`,
|
|
[ -requestedDuration, requestedMonitorId ],
|
|
));
|
|
|
|
const badgeValues = { style };
|
|
|
|
if (!publicAvgPing) {
|
|
// return a "N/A" badge in naColor (grey), if monitor is not public / not available / non existent
|
|
|
|
badgeValues.message = "N/A";
|
|
badgeValues.color = badgeConstants.naColor;
|
|
} else {
|
|
const avgPing = parseInt(overrideValue ?? publicAvgPing);
|
|
|
|
badgeValues.color = color;
|
|
// use a given, custom labelColor or use the default badge label color (defined by badge-maker)
|
|
badgeValues.labelColor = labelColor ?? "";
|
|
// build a label string. If a custom label is given, override the default one (requestedDuration)
|
|
badgeValues.label = filterAndJoin([
|
|
labelPrefix,
|
|
label ?? `Avg. Response (${requestedDuration}h)`,
|
|
labelSuffix,
|
|
]);
|
|
badgeValues.message = filterAndJoin([ prefix, avgPing, suffix ]);
|
|
}
|
|
|
|
// build the SVG based on given values
|
|
const svg = makeBadge(badgeValues);
|
|
|
|
response.type("image/svg+xml");
|
|
response.send(svg);
|
|
} catch (error) {
|
|
sendHttpError(response, error.message);
|
|
}
|
|
});
|
|
|
|
router.get("/api/badge/:id/cert-exp", cache("5 minutes"), async (request, response) => {
|
|
allowAllOrigin(response);
|
|
|
|
const date = request.query.date;
|
|
|
|
const {
|
|
label,
|
|
labelPrefix,
|
|
labelSuffix,
|
|
prefix,
|
|
suffix = date ? "" : badgeConstants.defaultCertExpValueSuffix,
|
|
upColor = badgeConstants.defaultUpColor,
|
|
warnColor = badgeConstants.defaultWarnColor,
|
|
downColor = badgeConstants.defaultDownColor,
|
|
warnDays = badgeConstants.defaultCertExpireWarnDays,
|
|
downDays = badgeConstants.defaultCertExpireDownDays,
|
|
labelColor,
|
|
style = badgeConstants.defaultStyle,
|
|
value, // for demo purpose only
|
|
} = request.query;
|
|
|
|
try {
|
|
const requestedMonitorId = parseInt(request.params.id, 10);
|
|
|
|
const overrideValue = value && parseFloat(value);
|
|
|
|
let publicMonitor = await R.getRow(`
|
|
SELECT monitor_group.monitor_id FROM monitor_group, \`group\`
|
|
WHERE monitor_group.group_id = \`group\`.id
|
|
AND monitor_group.monitor_id = ?
|
|
AND public = 1
|
|
`,
|
|
[ requestedMonitorId ],
|
|
);
|
|
|
|
const badgeValues = { style };
|
|
|
|
if (!publicMonitor) {
|
|
// return a "N/A" badge in naColor (grey), if monitor is not public / not available / non existent
|
|
|
|
badgeValues.message = "N/A";
|
|
badgeValues.color = badgeConstants.naColor;
|
|
} else {
|
|
const tlsInfoBean = await R.findOne("monitor_tls_info", "monitor_id = ?", [
|
|
requestedMonitorId,
|
|
]);
|
|
|
|
if (!tlsInfoBean) {
|
|
// return a "No/Bad Cert" badge in naColor (grey), if no cert saved (does not save bad certs?)
|
|
badgeValues.message = "No/Bad Cert";
|
|
badgeValues.color = badgeConstants.naColor;
|
|
} else {
|
|
const tlsInfo = JSON.parse(tlsInfoBean.info_json);
|
|
|
|
if (!tlsInfo.valid) {
|
|
// return a "Bad Cert" badge in naColor (grey), when cert is not valid
|
|
badgeValues.message = "Bad Cert";
|
|
badgeValues.color = downColor;
|
|
} else {
|
|
const daysRemaining = parseInt(overrideValue ?? tlsInfo.certInfo.daysRemaining);
|
|
|
|
if (daysRemaining > warnDays) {
|
|
badgeValues.color = upColor;
|
|
} else if (daysRemaining > downDays) {
|
|
badgeValues.color = warnColor;
|
|
} else {
|
|
badgeValues.color = downColor;
|
|
}
|
|
// use a given, custom labelColor or use the default badge label color (defined by badge-maker)
|
|
badgeValues.labelColor = labelColor ?? "";
|
|
// build a label string. If a custom label is given, override the default one
|
|
badgeValues.label = filterAndJoin([
|
|
labelPrefix,
|
|
label ?? "Cert Exp.",
|
|
labelSuffix,
|
|
]);
|
|
badgeValues.message = filterAndJoin([ prefix, date ? tlsInfo.certInfo.validTo : daysRemaining, suffix ]);
|
|
}
|
|
}
|
|
}
|
|
|
|
// build the SVG based on given values
|
|
const svg = makeBadge(badgeValues);
|
|
|
|
response.type("image/svg+xml");
|
|
response.send(svg);
|
|
} catch (error) {
|
|
sendHttpError(response, error.message);
|
|
}
|
|
});
|
|
|
|
router.get("/api/badge/:id/response", cache("5 minutes"), async (request, response) => {
|
|
allowAllOrigin(response);
|
|
|
|
const {
|
|
label,
|
|
labelPrefix,
|
|
labelSuffix,
|
|
prefix,
|
|
suffix = badgeConstants.defaultPingValueSuffix,
|
|
color = badgeConstants.defaultPingColor,
|
|
labelColor,
|
|
style = badgeConstants.defaultStyle,
|
|
value, // for demo purpose only
|
|
} = request.query;
|
|
|
|
try {
|
|
const requestedMonitorId = parseInt(request.params.id, 10);
|
|
|
|
const overrideValue = value && parseFloat(value);
|
|
|
|
let publicMonitor = await R.getRow(`
|
|
SELECT monitor_group.monitor_id FROM monitor_group, \`group\`
|
|
WHERE monitor_group.group_id = \`group\`.id
|
|
AND monitor_group.monitor_id = ?
|
|
AND public = 1
|
|
`,
|
|
[ requestedMonitorId ],
|
|
);
|
|
|
|
const badgeValues = { style };
|
|
|
|
if (!publicMonitor) {
|
|
// return a "N/A" badge in naColor (grey), if monitor is not public / not available / non existent
|
|
|
|
badgeValues.message = "N/A";
|
|
badgeValues.color = badgeConstants.naColor;
|
|
} else {
|
|
const heartbeat = await Monitor.getPreviousHeartbeat(
|
|
requestedMonitorId,
|
|
);
|
|
|
|
if (!heartbeat.ping) {
|
|
// return a "N/A" badge in naColor (grey), if previous heartbeat has no ping
|
|
|
|
badgeValues.message = "N/A";
|
|
badgeValues.color = badgeConstants.naColor;
|
|
} else {
|
|
const ping = parseInt(overrideValue ?? heartbeat.ping);
|
|
|
|
badgeValues.color = color;
|
|
// use a given, custom labelColor or use the default badge label color (defined by badge-maker)
|
|
badgeValues.labelColor = labelColor ?? "";
|
|
// build a label string. If a custom label is given, override the default one
|
|
badgeValues.label = filterAndJoin([
|
|
labelPrefix,
|
|
label ?? "Response",
|
|
labelSuffix,
|
|
]);
|
|
badgeValues.message = filterAndJoin([ prefix, ping, suffix ]);
|
|
}
|
|
}
|
|
|
|
// build the SVG based on given values
|
|
const svg = makeBadge(badgeValues);
|
|
|
|
response.type("image/svg+xml");
|
|
response.send(svg);
|
|
} catch (error) {
|
|
sendHttpError(response, error.message);
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Determines the status of the next beat in the push route handling.
|
|
* @param {string} status - The reported new status.
|
|
* @param {object} previousHeartbeat - The previous heartbeat object.
|
|
* @param {number} maxretries - The maximum number of retries allowed.
|
|
* @param {boolean} isUpsideDown - Indicates if the monitor is upside down.
|
|
* @param {object} bean - The new heartbeat object.
|
|
* @returns {void}
|
|
*/
|
|
function determineStatus(status, previousHeartbeat, maxretries, isUpsideDown, bean) {
|
|
if (isUpsideDown) {
|
|
status = flipStatus(status);
|
|
}
|
|
|
|
if (previousHeartbeat) {
|
|
if (previousHeartbeat.status === UP && status === DOWN) {
|
|
// Going Down
|
|
if ((maxretries > 0) && (previousHeartbeat.retries < maxretries)) {
|
|
// Retries available
|
|
bean.retries = previousHeartbeat.retries + 1;
|
|
bean.status = PENDING;
|
|
} else {
|
|
// No more retries
|
|
bean.retries = 0;
|
|
bean.status = DOWN;
|
|
}
|
|
} else if (previousHeartbeat.status === PENDING && status === DOWN && previousHeartbeat.retries < maxretries) {
|
|
// Retries available
|
|
bean.retries = previousHeartbeat.retries + 1;
|
|
bean.status = PENDING;
|
|
} else {
|
|
// No more retries or not pending
|
|
if (status === DOWN) {
|
|
bean.retries = previousHeartbeat.retries + 1;
|
|
bean.status = status;
|
|
} else {
|
|
bean.retries = 0;
|
|
bean.status = status;
|
|
}
|
|
}
|
|
} else {
|
|
// First beat?
|
|
if (status === DOWN && maxretries > 0) {
|
|
// Retries available
|
|
bean.retries = 1;
|
|
bean.status = PENDING;
|
|
} else {
|
|
// Retires not enabled
|
|
bean.retries = 0;
|
|
bean.status = status;
|
|
}
|
|
}
|
|
}
|
|
|
|
module.exports = router;
|