[WIP] Checking maintenance time using maintenance_timeslot table

This commit is contained in:
Louis Lam 2022-09-27 20:44:44 +08:00
parent 3f63cb246b
commit 4002b9f577
9 changed files with 75 additions and 13 deletions

View File

@ -0,0 +1,46 @@
const { BeanModel } = require("redbean-node/dist/bean-model");
const { R } = require("redbean-node");
const dayjs = require("dayjs");
class MaintenanceTimeslot extends BeanModel {
async toPublicJSON() {
}
async toJSON() {
}
/**
*
* @param {Maintenance} maintenance
* @param {dayjs} startFrom (For recurring type only) Generate Timeslot from this date, if it is smaller than the current date, it will use the current date instead. As generating a passed timeslot is meaningless.
* @param {boolean} removeExist Remove existing timeslot before create
* @returns {Promise<void>}
*/
static async generateTimeslot(maintenance, startFrom = null, removeExist = false) {
if (!startFrom) {
startFrom = dayjs();
}
if (removeExist) {
await R.exec("DELETE FROM maintenance_timeslot WHERE maintenance_id = ? ", [
maintenance.id
]);
}
if (maintenance.strategy === "single") {
let bean = R.dispense("maintenance_timeslot");
bean.maintenance_id = maintenance.id;
bean.start_date = maintenance.start_datetime;
bean.end_date = maintenance.end_datetime;
bean.generated_next = true;
await R.store(bean);
} else {
throw new Error("Unknown maintenance strategy");
}
}
}
module.exports = MaintenanceTimeslot;

View File

@ -1105,7 +1105,17 @@ class Monitor extends BeanModel {
* @returns {Promise<boolean>}
*/
static async isUnderMaintenance(monitorID) {
const maintenance = await R.getRow("SELECT COUNT(*) AS count FROM monitor_maintenance mm JOIN maintenance ON mm.maintenance_id = maintenance.id WHERE mm.monitor_id = ? AND datetime(maintenance.start_date) <= datetime('now') AND datetime(maintenance.end_date) >= datetime('now') LIMIT 1", [ monitorID ]);
const maintenance = await R.getRow(`
SELECT COUNT(*) AS count
FROM monitor_maintenance mm
JOIN maintenance
ON mm.maintenance_id = maintenance.id
JOIN maintenance_timeslot
ON maintenance_timeslot.maintenance_id = maintenance.id
WHERE mm.monitor_id = ?
AND maintenance_timeslot.start_date <= DATETIME('now')
AND maintenance_timeslot.end_date >= DATETIME('now')
LIMIT 1`, [ monitorID ]);
return maintenance.count !== 0;
}
}

View File

@ -273,11 +273,11 @@ class StatusPage extends BeanModel {
let maintenanceBeanList = R.convertToBeans("maintenance", await R.getAll(`
SELECT m.*
FROM maintenance m
JOIN maintenance_status_page msp
ON msp.maintenance_id = m.id
WHERE datetime(m.start_date) <= datetime('now')
AND datetime(m.end_date) >= datetime('now')
FROM maintenance m, maintenance_status_page msp, maintenance_timeslot
WHERE msp.maintenance_id = m.id
AND maintenance_timeslot.maintenance.id = m.id
AND maintenance_timeslot.start_date <= DATETIME('now')
AND maintenance_timeslot.end_date >= DATETIME('now')
AND msp.status_page_id = ?
ORDER BY m.end_date
`, [ statusPageId ]));

View File

@ -8,6 +8,7 @@ const server = UptimeKumaServer.getInstance();
const dayjs = require("dayjs");
const utc = require("dayjs/plugin/utc");
let timezone = require("dayjs/plugin/timezone");
const MaintenanceTimeslot = require("../model/maintenance_timeslot");
dayjs.extend(utc);
dayjs.extend(timezone);
@ -26,6 +27,7 @@ module.exports.maintenanceSocketHandler = (socket) => {
let bean = Maintenance.jsonToBean(R.dispense("maintenance"), maintenance, timezone);
bean.user_id = socket.userID;
let maintenanceID = await R.store(bean);
await MaintenanceTimeslot.generateTimeslot(bean);
await server.sendMaintenanceList(socket);
@ -57,6 +59,7 @@ module.exports.maintenanceSocketHandler = (socket) => {
Maintenance.jsonToBean(bean, maintenance, timezone);
await R.store(bean);
await MaintenanceTimeslot.generateTimeslot(bean, null, true);
await server.sendMaintenanceList(socket);

View File

@ -47,7 +47,7 @@ export default {
}
if (this.status === 3) {
return this.$t("Maintenance");
return this.$t("statusMaintenance");
}
return this.$t("Unknown");

View File

@ -26,7 +26,7 @@ export default {
uptime() {
if (this.type === "maintenance") {
return this.$t("Maintenance");
return this.$t("statusMaintenance");
}
let key = this.monitor.id + "_" + this.type;

View File

@ -10,6 +10,7 @@ export default {
maxRedirectDescription: "Maximum number of redirects to follow. Set to 0 to disable redirects.",
acceptedStatusCodesDescription: "Select status codes which are considered as a successful response.",
Maintenance: "Maintenance",
statusMaintenance: "Maintenance",
"Schedule maintenance": "Schedule maintenance",
"Affected Monitors": "Affected Monitors",
"Pick Affected Monitors...": "Pick Affected Monitors...",

View File

@ -380,4 +380,6 @@ export default {
proxyDescription: "必須將代理伺服器指派給監測器才能運作。",
enableProxyDescription: "此代理伺服器在啟用前不會在監測器上生效,您可以藉由控制啟用狀態來暫時對所有的監測器停用代理伺服器。",
setAsDefaultProxyDescription: "預設情況下,新監測器將啟用此代理伺服器。您仍可分別停用各監測器的代理伺服器。",
Maintenance: "維護",
statusMaintenance: "維護中",
};

View File

@ -588,7 +588,7 @@ export default {
if (this.monitorList[monitorID].maintenance) {
result[monitorID] = {
text: this.$t("Maintenance"),
text: this.$t("statusMaintenance"),
color: "maintenance",
};
} else if (! lastHeartBeat) {