111 lines
4.1 KiB
C#
111 lines
4.1 KiB
C#
using Elwig.Helpers;
|
|
using Elwig.Helpers.Export;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace Elwig.Services {
|
|
public static class BackupService {
|
|
|
|
public static bool IsAnyBackupUpToDate {
|
|
get {
|
|
var lastDbWrite = File.GetLastWriteTime(App.Config.DatabaseFile);
|
|
lastDbWrite += new TimeSpan(0, 0, -1);
|
|
return Directory.GetFiles(App.Config.BackupPath, "????-??-??_??-??-??.*.zip")
|
|
.Any(n => DateTime.ParseExact(Path.GetFileName(n)[..19], "yyyy-MM-dd_HH-mm-ss", CultureInfo.InvariantCulture, DateTimeStyles.None) >= lastDbWrite);
|
|
}
|
|
}
|
|
|
|
public static async Task TryDatabaseBackup() {
|
|
if (IsAnyBackupUpToDate) return;
|
|
await BackupDatabase();
|
|
PruneBackups();
|
|
}
|
|
|
|
public static async Task BackupDatabase() {
|
|
await Database.ExportSql(Path.Combine(App.Config.BackupPath, $"{File.GetLastWriteTime(App.Config.DatabaseFile):yyyy-MM-dd_HH-mm-ss}.sql.zip"), true);
|
|
}
|
|
|
|
public static void PruneBackups() {
|
|
var retain = new HashSet<string>();
|
|
var backups = Directory.GetFiles(App.Config.BackupPath, "????-??-??_??-??-??.*.zip")
|
|
.Select(n => (FileName: n, Timestamp: DateTime.ParseExact(Path.GetFileName(n)[..19], "yyyy-MM-dd_HH-mm-ss", CultureInfo.InvariantCulture, DateTimeStyles.None)))
|
|
.OrderByDescending(t => t.Timestamp).ToArray();
|
|
|
|
DateTime now;
|
|
|
|
// retain hourly backups
|
|
now = DateTime.Now;
|
|
for (int i = 0; i < App.Config.BackupRetainHours; i++, now = now.AddHours(-1)) {
|
|
foreach (var b in backups) {
|
|
if (b.Timestamp.Date == now.Date && b.Timestamp.Hour == now.Hour) {
|
|
retain.Add(b.FileName);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// retain daily backups
|
|
now = DateTime.Now;
|
|
for (int i = 0; i < App.Config.BackupRetainDays; i++, now = now.AddDays(-1)) {
|
|
foreach (var b in backups) {
|
|
if (b.Timestamp.Date == now.Date) {
|
|
retain.Add(b.FileName);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// retain weekly backups
|
|
now = DateTime.Now;
|
|
for (int i = 0; i < App.Config.BackupRetainWeeks; i++, now = now.AddDays(-7)) {
|
|
foreach (var b in backups) {
|
|
if (b.Timestamp.GetYearAndWeek() == now.GetYearAndWeek()) {
|
|
retain.Add(b.FileName);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// retain monthly backups
|
|
now = DateTime.Now;
|
|
for (int i = 0; i < App.Config.BackupRetainMonths; i++, now = now.AddMonths(-1)) {
|
|
foreach (var b in backups) {
|
|
if (b.Timestamp.Year == now.Year && b.Timestamp.Month == now.Month) {
|
|
retain.Add(b.FileName);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// retain tertial backups
|
|
now = new DateTime(DateTime.Now.Year + 1, 3, 1);
|
|
for (int i = 0; i < 600; i++, now = now.AddMonths(-4)) {
|
|
foreach (var b in backups) {
|
|
if (b.Timestamp.GetYearAndTertial() == now.GetYearAndTertial()) {
|
|
retain.Add(b.FileName);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// delete non-retained files
|
|
foreach (var b in backups) {
|
|
if (retain.Contains(b.FileName)) continue;
|
|
try {
|
|
File.Delete(b.FileName);
|
|
} catch { }
|
|
}
|
|
// delete temp files
|
|
foreach (var f in Directory.GetFiles(App.Config.BackupPath, "*.tmp")) {
|
|
try {
|
|
File.Delete(f);
|
|
} catch { }
|
|
}
|
|
}
|
|
}
|
|
}
|