Merge pull request #451 from moaazbhnas228/fix/heartbeat-grace-period

Fix: Heartbeat monitor respects cron-based grace periods
This commit is contained in:
Raj Nandan Sharma
2025-08-05 22:21:37 +05:30
committed by GitHub

View File

@@ -2,6 +2,7 @@
import { UP, DOWN, DEGRADED, REALTIME, TIMEOUT, ERROR, MANUAL } from "../constants.js";
import { GetMinuteStartNowTimestampUTC } from "../tool.js";
import { GetLastHeartbeat } from "../controllers/controller.js";
import { Cron } from "croner";
class HeartbeatCall {
monitor;
@@ -11,12 +12,37 @@ class HeartbeatCall {
}
async execute() {
let nowMinute = GetMinuteStartNowTimestampUTC();
let nowMinute = GetMinuteStartNowTimestampUTC(); // current time in seconds (minute start)
let latestData = await GetLastHeartbeat(this.monitor.tag);
if (!latestData) {
return {};
}
let latency = nowMinute - latestData.timestamp;
// Use croner to calculate expected heartbeat time
let expectedTime;
try {
const cronJob = Cron(this.monitor.cron);
const prevDate = cronJob.previousRun();
expectedTime = Math.floor(prevDate.getTime() / 1000); // seconds
} catch (err) {
return {
status: DOWN,
latency: 0,
type: ERROR,
};
}
// If heartbeat was received after or at expected time, it's UP
if (latestData.timestamp >= expectedTime) {
return {
status: UP,
latency: nowMinute - latestData.timestamp,
type: REALTIME,
};
}
// Calculate how late the expected heartbeat is
let latency = nowMinute - expectedTime;
let downRemainingMinutes = Number(this.monitor.type_data.downRemainingMinutes);
if (latency > downRemainingMinutes * 60) {
return {
@@ -25,6 +51,7 @@ class HeartbeatCall {
type: REALTIME,
};
}
let degradedRemainingMinutes = Number(this.monitor.type_data.degradedRemainingMinutes);
if (latency > degradedRemainingMinutes * 60) {
return {
@@ -33,6 +60,7 @@ class HeartbeatCall {
type: REALTIME,
};
}
return {
status: UP,
latency: latency,