Merge branch 'master' into feature/local-service-monitor
This commit is contained in:
commit
b64bf50379
@ -826,9 +826,7 @@ class Database {
|
||||
await Settings.set("migrateAggregateTableState", "migrating");
|
||||
|
||||
let progressPercent = 0;
|
||||
let part = 100 / monitors.length;
|
||||
let i = 1;
|
||||
for (let monitor of monitors) {
|
||||
for (const [ i, monitor ] of monitors.entries()) {
|
||||
// Get a list of unique dates from the heartbeat table, using raw sql
|
||||
let dates = await R.getAll(`
|
||||
SELECT DISTINCT DATE(time) AS date
|
||||
@ -839,7 +837,7 @@ class Database {
|
||||
monitor.monitor_id
|
||||
]);
|
||||
|
||||
for (let date of dates) {
|
||||
for (const [ dateIndex, date ] of dates.entries()) {
|
||||
// New Uptime Calculator
|
||||
let calculator = new UptimeCalculator();
|
||||
calculator.monitorID = monitor.monitor_id;
|
||||
@ -855,7 +853,7 @@ class Database {
|
||||
`, [ monitor.monitor_id, date.date ]);
|
||||
|
||||
if (heartbeats.length > 0) {
|
||||
msg = `[DON'T STOP] Migrating monitor data ${monitor.monitor_id} - ${date.date} [${progressPercent.toFixed(2)}%][${i}/${monitors.length}]`;
|
||||
msg = `[DON'T STOP] Migrating monitor ${monitor.monitor_id}s' (${i + 1} of ${monitors.length} total) data - ${date.date} - total migration progress ${progressPercent.toFixed(2)}%`;
|
||||
log.info("db", msg);
|
||||
migrationServer?.update(msg);
|
||||
}
|
||||
@ -864,15 +862,14 @@ class Database {
|
||||
await calculator.update(heartbeat.status, parseFloat(heartbeat.ping), dayjs(heartbeat.time));
|
||||
}
|
||||
|
||||
progressPercent += (Math.round(part / dates.length * 100) / 100);
|
||||
// Calculate progress: (current_monitor_index + relative_date_progress) / total_monitors
|
||||
progressPercent = (i + (dateIndex + 1) / dates.length) / monitors.length * 100;
|
||||
|
||||
// Lazy to fix the floating point issue, it is acceptable since it is just a progress bar
|
||||
if (progressPercent > 100) {
|
||||
progressPercent = 100;
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
msg = "Clearing non-important heartbeats";
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
const { BeanModel } = require("redbean-node/dist/bean-model");
|
||||
const { parseTimeObject, parseTimeFromTimeObject, log } = require("../../src/util");
|
||||
const { parseTimeObject, parseTimeFromTimeObject, log, SQL_DATETIME_FORMAT } = require("../../src/util");
|
||||
const { R } = require("redbean-node");
|
||||
const dayjs = require("dayjs");
|
||||
const Cron = require("croner");
|
||||
@ -262,7 +262,7 @@ class Maintenance extends BeanModel {
|
||||
}, duration);
|
||||
|
||||
// Set last start date to current time
|
||||
this.last_start_date = current.toISOString();
|
||||
this.last_start_date = current.utc().format(SQL_DATETIME_FORMAT);
|
||||
await R.store(this);
|
||||
};
|
||||
|
||||
|
||||
65
test/backend-test/test-maintenance.js
Normal file
65
test/backend-test/test-maintenance.js
Normal file
@ -0,0 +1,65 @@
|
||||
const test = require("node:test");
|
||||
const assert = require("node:assert");
|
||||
const dayjs = require("dayjs");
|
||||
const { SQL_DATETIME_FORMAT } = require("../../src/util");
|
||||
|
||||
dayjs.extend(require("dayjs/plugin/utc"));
|
||||
dayjs.extend(require("dayjs/plugin/customParseFormat"));
|
||||
|
||||
/**
|
||||
* Tests for maintenance date formatting to ensure compatibility with MariaDB/MySQL.
|
||||
* Issue: MariaDB rejects ISO format dates like '2025-12-19T01:04:02.129Z'
|
||||
* Fix: Use SQL_DATETIME_FORMAT ('YYYY-MM-DD HH:mm:ss') instead of toISOString()
|
||||
*/
|
||||
test("Maintenance Date Format - MariaDB Compatibility", async (t) => {
|
||||
|
||||
await t.test("SQL_DATETIME_FORMAT constant should match MariaDB format", async () => {
|
||||
assert.strictEqual(SQL_DATETIME_FORMAT, "YYYY-MM-DD HH:mm:ss");
|
||||
});
|
||||
|
||||
await t.test("Format date using SQL_DATETIME_FORMAT", async () => {
|
||||
const current = dayjs.utc("2025-12-19T01:04:02.129Z");
|
||||
const sqlFormat = current.utc().format(SQL_DATETIME_FORMAT);
|
||||
|
||||
assert.strictEqual(sqlFormat, "2025-12-19 01:04:02");
|
||||
});
|
||||
|
||||
await t.test("SQL format should not contain ISO markers (T, Z)", async () => {
|
||||
const current = dayjs.utc("2025-12-19T01:04:02.129Z");
|
||||
const sqlFormat = current.utc().format(SQL_DATETIME_FORMAT);
|
||||
|
||||
assert.strictEqual(sqlFormat.includes("T"), false, "SQL format should not contain 'T'");
|
||||
assert.strictEqual(sqlFormat.includes("Z"), false, "SQL format should not contain 'Z'");
|
||||
});
|
||||
|
||||
await t.test("SQL format should match YYYY-MM-DD HH:mm:ss pattern", async () => {
|
||||
const current = dayjs.utc("2025-12-19T01:04:02.129Z");
|
||||
const sqlFormat = current.utc().format(SQL_DATETIME_FORMAT);
|
||||
const sqlDateTimeRegex = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/;
|
||||
|
||||
assert.strictEqual(sqlDateTimeRegex.test(sqlFormat), true);
|
||||
});
|
||||
|
||||
await t.test("Parse SQL datetime back to dayjs preserves timestamp", async () => {
|
||||
const originalDate = dayjs.utc("2025-12-19T01:04:02.000Z");
|
||||
const sqlFormat = originalDate.utc().format(SQL_DATETIME_FORMAT);
|
||||
const parsedDate = dayjs.utc(sqlFormat, SQL_DATETIME_FORMAT);
|
||||
|
||||
assert.strictEqual(parsedDate.unix(), originalDate.unix());
|
||||
});
|
||||
|
||||
await t.test("Edge case: midnight timestamp", async () => {
|
||||
const midnight = dayjs.utc("2025-01-01T00:00:00.000Z");
|
||||
const sqlFormat = midnight.utc().format(SQL_DATETIME_FORMAT);
|
||||
|
||||
assert.strictEqual(sqlFormat, "2025-01-01 00:00:00");
|
||||
});
|
||||
|
||||
await t.test("Edge case: end of day timestamp", async () => {
|
||||
const endOfDay = dayjs.utc("2025-12-31T23:59:59.999Z");
|
||||
const sqlFormat = endOfDay.utc().format(SQL_DATETIME_FORMAT);
|
||||
|
||||
assert.strictEqual(sqlFormat, "2025-12-31 23:59:59");
|
||||
});
|
||||
|
||||
});
|
||||
Loading…
Reference in New Issue
Block a user