From 6a69c6ccc0fde8ed2c3d8809afb94b44a0cab854 Mon Sep 17 00:00:00 2001 From: leonace924 Date: Mon, 5 Jan 2026 20:43:03 -0500 Subject: [PATCH 1/6] fix: push monitor retry and notification issue --- server/model/monitor.js | 5 +++-- server/routers/api-router.js | 16 ++++++++++++++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/server/model/monitor.js b/server/model/monitor.js index ed4bb219c..904268aa9 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -1294,7 +1294,7 @@ class Monitor extends BeanModel { // UP -> UP = not important // PENDING -> PENDING = not important // * PENDING -> DOWN = important - // PENDING -> UP = not important + // * PENDING -> UP = important (recovery from potential trouble) // DOWN -> PENDING = this case not exists // DOWN -> DOWN = not important // * DOWN -> UP = important @@ -1307,7 +1307,8 @@ class Monitor extends BeanModel { (previousBeatStatus === MAINTENANCE && currentBeatStatus === DOWN) || (previousBeatStatus === UP && currentBeatStatus === DOWN) || (previousBeatStatus === DOWN && currentBeatStatus === UP) || - (previousBeatStatus === PENDING && currentBeatStatus === DOWN); + (previousBeatStatus === PENDING && currentBeatStatus === DOWN) || + (previousBeatStatus === PENDING && currentBeatStatus === UP); } /** diff --git a/server/routers/api-router.js b/server/routers/api-router.js index 9c9a7e7e9..4a432fe4a 100644 --- a/server/routers/api-router.js +++ b/server/routers/api-router.js @@ -52,6 +52,10 @@ router.all("/api/push/:pushToken", async (request, response) => { let statusString = request.query.status || "up"; const statusFromParam = (statusString === "up") ? UP : DOWN; + // Check if status=down was explicitly provided (not defaulting to "up") + // When explicitly pushing down, bypass retry logic and go directly to DOWN + const isExplicitDown = request.query.status === "down"; + let monitor = await R.findOne("monitor", " push_token = ? AND active = 1 ", [ pushToken ]); @@ -80,7 +84,7 @@ router.all("/api/push/:pushToken", async (request, response) => { msg = "Monitor under maintenance"; bean.status = MAINTENANCE; } else { - determineStatus(statusFromParam, previousHeartbeat, monitor.maxretries, monitor.isUpsideDown(), bean); + determineStatus(statusFromParam, previousHeartbeat, monitor.maxretries, monitor.isUpsideDown(), bean, isExplicitDown); } // Calculate uptime @@ -586,13 +590,21 @@ router.get("/api/badge/:id/response", cache("5 minutes"), async (request, respon * @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. + * @param {boolean} isExplicitDown - If status=down was explicitly pushed, bypass retries. * @returns {void} */ -function determineStatus(status, previousHeartbeat, maxretries, isUpsideDown, bean) { +function determineStatus(status, previousHeartbeat, maxretries, isUpsideDown, bean, isExplicitDown = false) { if (isUpsideDown) { status = flipStatus(status); } + // If status=down was explicitly pushed, bypass retry logic and go directly to DOWN + if (isExplicitDown && status === DOWN) { + bean.retries = 0; + bean.status = DOWN; + return; + } + if (previousHeartbeat) { if (previousHeartbeat.status === UP && status === DOWN) { // Going Down From 44671022bba2a528df22597f0b642714a12271a8 Mon Sep 17 00:00:00 2001 From: leonace924 Date: Mon, 5 Jan 2026 21:07:26 -0500 Subject: [PATCH 2/6] fix: revert 6406 --- server/routers/api-router.js | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/server/routers/api-router.js b/server/routers/api-router.js index 4a432fe4a..9c9a7e7e9 100644 --- a/server/routers/api-router.js +++ b/server/routers/api-router.js @@ -52,10 +52,6 @@ router.all("/api/push/:pushToken", async (request, response) => { let statusString = request.query.status || "up"; const statusFromParam = (statusString === "up") ? UP : DOWN; - // Check if status=down was explicitly provided (not defaulting to "up") - // When explicitly pushing down, bypass retry logic and go directly to DOWN - const isExplicitDown = request.query.status === "down"; - let monitor = await R.findOne("monitor", " push_token = ? AND active = 1 ", [ pushToken ]); @@ -84,7 +80,7 @@ router.all("/api/push/:pushToken", async (request, response) => { msg = "Monitor under maintenance"; bean.status = MAINTENANCE; } else { - determineStatus(statusFromParam, previousHeartbeat, monitor.maxretries, monitor.isUpsideDown(), bean, isExplicitDown); + determineStatus(statusFromParam, previousHeartbeat, monitor.maxretries, monitor.isUpsideDown(), bean); } // Calculate uptime @@ -590,21 +586,13 @@ router.get("/api/badge/:id/response", cache("5 minutes"), async (request, respon * @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. - * @param {boolean} isExplicitDown - If status=down was explicitly pushed, bypass retries. * @returns {void} */ -function determineStatus(status, previousHeartbeat, maxretries, isUpsideDown, bean, isExplicitDown = false) { +function determineStatus(status, previousHeartbeat, maxretries, isUpsideDown, bean) { if (isUpsideDown) { status = flipStatus(status); } - // If status=down was explicitly pushed, bypass retry logic and go directly to DOWN - if (isExplicitDown && status === DOWN) { - bean.retries = 0; - bean.status = DOWN; - return; - } - if (previousHeartbeat) { if (previousHeartbeat.status === UP && status === DOWN) { // Going Down From 7ff8da9266b69c5b400b923b175b01cd55414b82 Mon Sep 17 00:00:00 2001 From: leonace924 Date: Mon, 5 Jan 2026 21:17:30 -0500 Subject: [PATCH 3/6] fix: implement 6406 issue --- server/model/monitor.js | 4 +--- server/routers/api-router.js | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/server/model/monitor.js b/server/model/monitor.js index 904268aa9..4bba2c16c 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -1294,7 +1294,6 @@ class Monitor extends BeanModel { // UP -> UP = not important // PENDING -> PENDING = not important // * PENDING -> DOWN = important - // * PENDING -> UP = important (recovery from potential trouble) // DOWN -> PENDING = this case not exists // DOWN -> DOWN = not important // * DOWN -> UP = important @@ -1307,8 +1306,7 @@ class Monitor extends BeanModel { (previousBeatStatus === MAINTENANCE && currentBeatStatus === DOWN) || (previousBeatStatus === UP && currentBeatStatus === DOWN) || (previousBeatStatus === DOWN && currentBeatStatus === UP) || - (previousBeatStatus === PENDING && currentBeatStatus === DOWN) || - (previousBeatStatus === PENDING && currentBeatStatus === UP); + (previousBeatStatus === PENDING && currentBeatStatus === DOWN); } /** diff --git a/server/routers/api-router.js b/server/routers/api-router.js index 9c9a7e7e9..4a432fe4a 100644 --- a/server/routers/api-router.js +++ b/server/routers/api-router.js @@ -52,6 +52,10 @@ router.all("/api/push/:pushToken", async (request, response) => { let statusString = request.query.status || "up"; const statusFromParam = (statusString === "up") ? UP : DOWN; + // Check if status=down was explicitly provided (not defaulting to "up") + // When explicitly pushing down, bypass retry logic and go directly to DOWN + const isExplicitDown = request.query.status === "down"; + let monitor = await R.findOne("monitor", " push_token = ? AND active = 1 ", [ pushToken ]); @@ -80,7 +84,7 @@ router.all("/api/push/:pushToken", async (request, response) => { msg = "Monitor under maintenance"; bean.status = MAINTENANCE; } else { - determineStatus(statusFromParam, previousHeartbeat, monitor.maxretries, monitor.isUpsideDown(), bean); + determineStatus(statusFromParam, previousHeartbeat, monitor.maxretries, monitor.isUpsideDown(), bean, isExplicitDown); } // Calculate uptime @@ -586,13 +590,21 @@ router.get("/api/badge/:id/response", cache("5 minutes"), async (request, respon * @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. + * @param {boolean} isExplicitDown - If status=down was explicitly pushed, bypass retries. * @returns {void} */ -function determineStatus(status, previousHeartbeat, maxretries, isUpsideDown, bean) { +function determineStatus(status, previousHeartbeat, maxretries, isUpsideDown, bean, isExplicitDown = false) { if (isUpsideDown) { status = flipStatus(status); } + // If status=down was explicitly pushed, bypass retry logic and go directly to DOWN + if (isExplicitDown && status === DOWN) { + bean.retries = 0; + bean.status = DOWN; + return; + } + if (previousHeartbeat) { if (previousHeartbeat.status === UP && status === DOWN) { // Going Down From 0b1d434b82d6db9f2d041da6d6d9e011d2b40436 Mon Sep 17 00:00:00 2001 From: Pegasus <42954461+leonace924@users.noreply.github.com> Date: Mon, 5 Jan 2026 23:15:05 -0500 Subject: [PATCH 4/6] Update server/routers/api-router.js Co-authored-by: Frank Elsinga --- server/routers/api-router.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/routers/api-router.js b/server/routers/api-router.js index 4a432fe4a..79f6aa58d 100644 --- a/server/routers/api-router.js +++ b/server/routers/api-router.js @@ -593,7 +593,7 @@ router.get("/api/badge/:id/response", cache("5 minutes"), async (request, respon * @param {boolean} isExplicitDown - If status=down was explicitly pushed, bypass retries. * @returns {void} */ -function determineStatus(status, previousHeartbeat, maxretries, isUpsideDown, bean, isExplicitDown = false) { +function determineStatus(status, previousHeartbeat, maxretries, isUpsideDown, bean, isExplicitDown) { if (isUpsideDown) { status = flipStatus(status); } From b1b8bd67cd02ac4cee5c3c63a1c7562fd3b2aa3a Mon Sep 17 00:00:00 2001 From: Pegasus <42954461+leonace924@users.noreply.github.com> Date: Mon, 5 Jan 2026 23:15:23 -0500 Subject: [PATCH 5/6] Update server/model/monitor.js Co-authored-by: Frank Elsinga --- server/model/monitor.js | 1 + 1 file changed, 1 insertion(+) diff --git a/server/model/monitor.js b/server/model/monitor.js index 4bba2c16c..2f759a53d 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -1294,6 +1294,7 @@ class Monitor extends BeanModel { // UP -> UP = not important // PENDING -> PENDING = not important // * PENDING -> DOWN = important + // * PENDING -> UP = not important // DOWN -> PENDING = this case not exists // DOWN -> DOWN = not important // * DOWN -> UP = important From 4657988d9128d9b51ed4dbef337e7ca2e78f6114 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Fri, 9 Jan 2026 02:43:24 +0000 Subject: [PATCH 6/6] [autofix.ci] apply automated fixes --- server/routers/api-router.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/server/routers/api-router.js b/server/routers/api-router.js index 960ded6a4..c11b95a4f 100644 --- a/server/routers/api-router.js +++ b/server/routers/api-router.js @@ -56,9 +56,7 @@ router.all("/api/push/:pushToken", async (request, response) => { // When explicitly pushing down, bypass retry logic and go directly to DOWN const isExplicitDown = request.query.status === "down"; - let monitor = await R.findOne("monitor", " push_token = ? AND active = 1 ", [ - pushToken - ]); + let monitor = await R.findOne("monitor", " push_token = ? AND active = 1 ", [pushToken]); if (!monitor) { throw new Error("Monitor not found or not active."); @@ -84,7 +82,14 @@ router.all("/api/push/:pushToken", async (request, response) => { msg = "Monitor under maintenance"; bean.status = MAINTENANCE; } else { - determineStatus(statusFromParam, previousHeartbeat, monitor.maxretries, monitor.isUpsideDown(), bean, isExplicitDown); + determineStatus( + statusFromParam, + previousHeartbeat, + monitor.maxretries, + monitor.isUpsideDown(), + bean, + isExplicitDown + ); } // Calculate uptime