2017-10-21 21:10:33 -04:00
|
|
|
"use strict";
|
|
|
|
|
2024-07-18 21:35:17 +03:00
|
|
|
import dateUtils from "./date_utils.js";
|
2025-01-04 11:52:40 +02:00
|
|
|
import optionService from "./options.js";
|
2024-07-18 21:37:45 +03:00
|
|
|
import fs from "fs-extra";
|
2024-07-18 21:35:17 +03:00
|
|
|
import dataDir from "./data_dir.js";
|
|
|
|
import log from "./log.js";
|
|
|
|
import syncMutexService from "./sync_mutex.js";
|
|
|
|
import cls from "./cls.js";
|
|
|
|
import sql from "./sql.js";
|
2024-07-18 21:37:45 +03:00
|
|
|
import path from "path";
|
2025-01-04 11:52:40 +02:00
|
|
|
import type { OptionNames } from "./options_interface.js";
|
2024-02-17 19:33:29 +02:00
|
|
|
|
2025-01-09 18:07:02 +02:00
|
|
|
type BackupType = "daily" | "weekly" | "monthly";
|
2023-10-18 23:16:47 +02:00
|
|
|
|
|
|
|
function getExistingBackups() {
|
|
|
|
if (!fs.existsSync(dataDir.BACKUP_DIR)) {
|
|
|
|
return [];
|
|
|
|
}
|
|
|
|
|
2025-01-09 18:07:02 +02:00
|
|
|
return fs
|
|
|
|
.readdirSync(dataDir.BACKUP_DIR)
|
|
|
|
.filter((fileName) => fileName.includes("backup"))
|
|
|
|
.map((fileName) => {
|
2023-10-19 00:51:38 +02:00
|
|
|
const filePath = path.resolve(dataDir.BACKUP_DIR, fileName);
|
2025-01-09 18:07:02 +02:00
|
|
|
const stat = fs.statSync(filePath);
|
2023-10-19 00:51:38 +02:00
|
|
|
|
2025-01-09 18:07:02 +02:00
|
|
|
return { fileName, filePath, mtime: stat.mtime };
|
2023-10-19 00:51:38 +02:00
|
|
|
});
|
2023-10-18 23:16:47 +02:00
|
|
|
}
|
2017-10-14 23:31:44 -04:00
|
|
|
|
2020-06-20 12:31:38 +02:00
|
|
|
function regularBackup() {
|
2020-07-04 00:20:23 +02:00
|
|
|
cls.init(() => {
|
2025-01-09 18:07:02 +02:00
|
|
|
periodBackup("lastDailyBackupDate", "daily", 24 * 3600);
|
2018-07-30 16:40:50 +02:00
|
|
|
|
2025-01-09 18:07:02 +02:00
|
|
|
periodBackup("lastWeeklyBackupDate", "weekly", 7 * 24 * 3600);
|
2018-07-30 16:40:50 +02:00
|
|
|
|
2025-01-09 18:07:02 +02:00
|
|
|
periodBackup("lastMonthlyBackupDate", "monthly", 30 * 24 * 3600);
|
2020-07-04 00:20:23 +02:00
|
|
|
});
|
2018-07-30 16:40:50 +02:00
|
|
|
}
|
|
|
|
|
2024-02-17 19:33:29 +02:00
|
|
|
function isBackupEnabled(backupType: BackupType) {
|
2025-01-03 17:54:05 +02:00
|
|
|
let optionName: OptionNames;
|
|
|
|
switch (backupType) {
|
|
|
|
case "daily":
|
|
|
|
optionName = "dailyBackupEnabled";
|
|
|
|
break;
|
|
|
|
case "weekly":
|
|
|
|
optionName = "weeklyBackupEnabled";
|
|
|
|
break;
|
|
|
|
case "monthly":
|
|
|
|
optionName = "monthlyBackupEnabled";
|
|
|
|
break;
|
|
|
|
}
|
2021-10-11 22:30:23 +02:00
|
|
|
|
|
|
|
return optionService.getOptionBool(optionName);
|
|
|
|
}
|
|
|
|
|
2025-01-03 17:54:05 +02:00
|
|
|
function periodBackup(optionName: "lastDailyBackupDate" | "lastWeeklyBackupDate" | "lastMonthlyBackupDate", backupType: BackupType, periodInSeconds: number) {
|
2021-10-11 22:30:23 +02:00
|
|
|
if (!isBackupEnabled(backupType)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-12-10 12:56:59 -05:00
|
|
|
const now = new Date();
|
2021-10-11 22:30:23 +02:00
|
|
|
const lastBackupDate = dateUtils.parseDateTime(optionService.getOption(optionName));
|
2017-10-14 23:31:44 -04:00
|
|
|
|
2021-10-11 22:30:23 +02:00
|
|
|
if (now.getTime() - lastBackupDate.getTime() > periodInSeconds * 1000) {
|
|
|
|
backupNow(backupType);
|
2017-12-10 12:56:59 -05:00
|
|
|
|
2020-06-20 12:31:38 +02:00
|
|
|
optionService.setOption(optionName, dateUtils.utcNowDateTime());
|
2017-10-14 23:31:44 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-17 19:33:29 +02:00
|
|
|
async function backupNow(name: string) {
|
2022-01-17 23:47:26 +01:00
|
|
|
// we don't want to back up DB in the middle of sync with potentially inconsistent DB state
|
2020-06-20 23:09:34 +02:00
|
|
|
return await syncMutexService.doExclusively(async () => {
|
2018-07-30 16:40:50 +02:00
|
|
|
const backupFile = `${dataDir.BACKUP_DIR}/backup-${name}.db`;
|
2017-10-24 22:17:48 -04:00
|
|
|
|
2025-03-24 17:42:38 +02:00
|
|
|
if (!fs.existsSync(dataDir.BACKUP_DIR)) {
|
|
|
|
fs.mkdirSync(dataDir.BACKUP_DIR, 0o700);
|
|
|
|
}
|
|
|
|
|
2022-01-17 23:47:26 +01:00
|
|
|
await sql.copyDatabase(backupFile);
|
2020-05-29 21:55:08 +02:00
|
|
|
|
2022-12-21 15:19:05 +01:00
|
|
|
log.info(`Created backup at ${backupFile}`);
|
2017-10-14 23:31:44 -04:00
|
|
|
|
2020-05-29 21:55:08 +02:00
|
|
|
return backupFile;
|
2017-10-14 23:31:44 -04:00
|
|
|
});
|
|
|
|
}
|
2024-07-18 21:47:30 +03:00
|
|
|
export default {
|
2023-10-18 23:16:47 +02:00
|
|
|
getExistingBackups,
|
2020-06-02 23:13:55 +02:00
|
|
|
backupNow,
|
2020-07-02 22:57:17 +02:00
|
|
|
regularBackup
|
2020-05-29 21:55:08 +02:00
|
|
|
};
|