diff --git a/src/lib/server/services/heartbeatCall.js b/src/lib/server/services/heartbeatCall.js index 652f568..5ff1b05 100644 --- a/src/lib/server/services/heartbeatCall.js +++ b/src/lib/server/services/heartbeatCall.js @@ -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,