zwave-js-ui
Version:
Z-Wave Control Panel and MQTT Gateway
106 lines (105 loc) • 3.98 kB
JavaScript
import store from "../config/store.js";
import { module } from "./logger.js";
import jsonStore, { STORE_BACKUP_PREFIX } from "./jsonStore.js";
import Cron from 'croner';
import { readdir, unlink } from 'node:fs/promises';
import { nvmBackupsDir, storeBackupsDir } from "../config/app.js";
import { joinPath } from "./utils.js";
export const NVM_BACKUP_PREFIX = 'NVM_';
const logger = module('Backup');
class BackupManager {
config;
storeJob;
nvmJob;
zwaveClient;
get default() {
return {
storeBackup: false,
storeCron: '0 0 * * *',
storeKeep: 7,
nvmBackup: false,
nvmBackupOnEvent: false,
nvmCron: '0 0 * * *',
nvmKeep: 7,
};
}
get backupOnEvent() {
return this.config.nvmBackupOnEvent;
}
nextRun(job) {
if (job?.nextRun()) {
return job.nextRun().toLocaleString();
}
return 'UNKNOWN';
}
init(zwaveClient) {
this.config = {
...this.default,
...jsonStore.get(store.settings).backup,
};
this.zwaveClient = zwaveClient;
if (this.storeJob) {
this.storeJob.stop();
}
if (!this.config.storeBackup) {
logger.warn('Store backup is disabled');
}
else {
this.storeJob = new Cron(this.config.storeCron, this.backupStore.bind(this));
logger.info(`Backup job started with cron: ${this.config.storeCron}. Next run: ${this.nextRun(this.storeJob)}`);
}
if (this.nvmJob) {
this.nvmJob.stop();
}
if (!this.config.nvmBackup) {
logger.warn('Nvm backup is disabled');
}
else {
this.nvmJob = new Cron(this.config.nvmCron, this.backupNvm.bind(this));
logger.info(`Backup job started with cron: ${this.config.nvmCron}. Next run: ${this.nextRun(this.nvmJob)}`);
}
}
async backupNvm() {
logger.info('Backup NVM started');
try {
const { fileName } = await this.zwaveClient.backupNVMRaw();
logger.info(`Backup NVM created: ${fileName}`);
if (this.nvmJob) {
logger.info(`Next NVM backup: ${this.nextRun(this.nvmJob)}`);
}
// cleanup backups dir, keep last backup files
const backups = (await readdir(nvmBackupsDir)).filter((f) => f.startsWith(NVM_BACKUP_PREFIX));
// keep last `keep` backups
if (backups.length > this.config.nvmKeep) {
const toDelete = backups.slice(0, backups.length - this.config.nvmKeep);
await Promise.all(toDelete.map(async (file) => unlink(joinPath(nvmBackupsDir, file))));
logger.info(`Deleted ${toDelete.length} old NVM backups`);
}
}
catch (err) {
logger.error('Backup NVM failed', err);
}
}
async backupStore() {
logger.info('Backup STORE started');
try {
const backupFile = await jsonStore.backup();
logger.info(`Backup STORE created: ${backupFile}`);
if (this.storeJob) {
logger.info(`Next STORE backup: ${this.nextRun(this.storeJob)}`);
}
// cleanup backups dir, keep last backup files
const backups = (await readdir(storeBackupsDir)).filter((f) => f.startsWith(STORE_BACKUP_PREFIX));
// keep last `keep` backups
if (backups.length > this.config.storeKeep) {
const toDelete = backups.slice(0, backups.length - this.config.storeKeep);
await Promise.all(toDelete.map(async (file) => unlink(joinPath(storeBackupsDir, file))));
logger.info(`Deleted ${toDelete.length} old STORE backups`);
}
}
catch (err) {
logger.error('Backup STORE failed', err);
}
}
}
export default new BackupManager();