Dieser Commit ist enthalten in:
Claude Project Manager
2025-12-28 21:36:45 +00:00
Commit ab1e5be9a9
146 geänderte Dateien mit 65525 neuen und 0 gelöschten Zeilen

183
backend/utils/backup.js Normale Datei
Datei anzeigen

@ -0,0 +1,183 @@
/**
* TASKMATE - Backup System
* ========================
* Automatische Datenbank-Backups
*/
const fs = require('fs');
const path = require('path');
const logger = require('./logger');
const DATA_DIR = process.env.DATA_DIR || path.join(__dirname, '..', 'data');
const BACKUP_DIR = process.env.BACKUP_DIR || path.join(__dirname, '..', 'backups');
const DB_FILE = path.join(DATA_DIR, 'taskmate.db');
// Backup-Verzeichnis erstellen falls nicht vorhanden
if (!fs.existsSync(BACKUP_DIR)) {
fs.mkdirSync(BACKUP_DIR, { recursive: true });
}
/**
* Backup erstellen
*/
function createBackup() {
try {
if (!fs.existsSync(DB_FILE)) {
logger.warn('Keine Datenbank zum Sichern gefunden');
return null;
}
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
const backupName = `backup_${timestamp}.db`;
const backupPath = path.join(BACKUP_DIR, backupName);
// Datenbank kopieren
fs.copyFileSync(DB_FILE, backupPath);
// WAL-Datei auch sichern falls vorhanden
const walFile = DB_FILE + '-wal';
if (fs.existsSync(walFile)) {
fs.copyFileSync(walFile, backupPath + '-wal');
}
logger.info(`Backup erstellt: ${backupName}`);
// Alte Backups aufräumen (behalte nur die letzten 30)
cleanupOldBackups(30);
return backupPath;
} catch (error) {
logger.error('Backup-Fehler:', { error: error.message });
return null;
}
}
/**
* Alte Backups löschen
*/
function cleanupOldBackups(keepCount = 30) {
try {
const files = fs.readdirSync(BACKUP_DIR)
.filter(f => f.startsWith('backup_') && f.endsWith('.db'))
.sort()
.reverse();
const toDelete = files.slice(keepCount);
toDelete.forEach(file => {
const filePath = path.join(BACKUP_DIR, file);
fs.unlinkSync(filePath);
// WAL-Datei auch löschen falls vorhanden
const walPath = filePath + '-wal';
if (fs.existsSync(walPath)) {
fs.unlinkSync(walPath);
}
logger.info(`Altes Backup gelöscht: ${file}`);
});
} catch (error) {
logger.error('Fehler beim Aufräumen alter Backups:', { error: error.message });
}
}
/**
* Backup wiederherstellen
*/
function restoreBackup(backupName) {
try {
const backupPath = path.join(BACKUP_DIR, backupName);
if (!fs.existsSync(backupPath)) {
throw new Error(`Backup nicht gefunden: ${backupName}`);
}
// Aktuelles DB sichern bevor überschrieben wird
if (fs.existsSync(DB_FILE)) {
const safetyBackup = DB_FILE + '.before-restore';
fs.copyFileSync(DB_FILE, safetyBackup);
}
// Backup wiederherstellen
fs.copyFileSync(backupPath, DB_FILE);
// WAL-Datei auch wiederherstellen falls vorhanden
const walBackup = backupPath + '-wal';
if (fs.existsSync(walBackup)) {
fs.copyFileSync(walBackup, DB_FILE + '-wal');
}
logger.info(`Backup wiederhergestellt: ${backupName}`);
return true;
} catch (error) {
logger.error('Restore-Fehler:', { error: error.message });
throw error;
}
}
/**
* Liste aller Backups
*/
function listBackups() {
try {
const files = fs.readdirSync(BACKUP_DIR)
.filter(f => f.startsWith('backup_') && f.endsWith('.db'))
.map(f => {
const filePath = path.join(BACKUP_DIR, f);
const stats = fs.statSync(filePath);
return {
name: f,
size: stats.size,
created: stats.birthtime
};
})
.sort((a, b) => b.created - a.created);
return files;
} catch (error) {
logger.error('Fehler beim Auflisten der Backups:', { error: error.message });
return [];
}
}
/**
* Backup-Scheduler starten
*/
let schedulerInterval = null;
function startScheduler() {
const intervalHours = parseInt(process.env.BACKUP_INTERVAL_HOURS) || 24;
const intervalMs = intervalHours * 60 * 60 * 1000;
// Erstes Backup nach 1 Minute
setTimeout(() => {
createBackup();
}, 60 * 1000);
// Regelmäßige Backups
schedulerInterval = setInterval(() => {
createBackup();
}, intervalMs);
logger.info(`Backup-Scheduler gestartet (alle ${intervalHours} Stunden)`);
}
/**
* Backup-Scheduler stoppen
*/
function stopScheduler() {
if (schedulerInterval) {
clearInterval(schedulerInterval);
schedulerInterval = null;
logger.info('Backup-Scheduler gestoppt');
}
}
module.exports = {
createBackup,
restoreBackup,
listBackups,
startScheduler,
stopScheduler,
cleanupOldBackups
};