diff --git a/server/model/monitor.js b/server/model/monitor.js index 33256fbfd6..29ead535dc 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -1371,7 +1371,7 @@ class Monitor extends BeanModel { // UP -> UP = not important // PENDING -> PENDING = not important // * PENDING -> DOWN = important - // PENDING -> UP = not important + // * PENDING -> UP = not important // DOWN -> PENDING = this case not exists // DOWN -> DOWN = not important // * DOWN -> UP = important diff --git a/server/routers/api-router.js b/server/routers/api-router.js index 8f6d092481..c11b95a4f5 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]); if (!monitor) { @@ -78,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); + determineStatus( + statusFromParam, + previousHeartbeat, + monitor.maxretries, + monitor.isUpsideDown(), + bean, + isExplicitDown + ); } // Calculate uptime @@ -584,13 +595,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) { 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