96 lines
3.3 KiB
C#
96 lines
3.3 KiB
C#
using System.Diagnostics;
|
|
using Cronos;
|
|
|
|
namespace OneDriveBackupService;
|
|
|
|
public class Worker(ILogger<Worker> logger, ConfigData config, OneDriveClient client) : BackgroundService {
|
|
protected override async Task ExecuteAsync(CancellationToken stoppingToken) {
|
|
await client.EnsureAuthenticated(stoppingToken);
|
|
|
|
if (Environment.GetCommandLineArgs().Contains("--run-once")) {
|
|
logger.LogInformation("Manual backup triggered");
|
|
await RunBackup(DateTime.Now, stoppingToken);
|
|
return;
|
|
}
|
|
|
|
var expression = CronExpression.Parse(config.Schedule);
|
|
|
|
while (!stoppingToken.IsCancellationRequested) {
|
|
var utcNow = DateTime.UtcNow;
|
|
|
|
var cronTime = expression.GetNextOccurrence(utcNow);
|
|
var delay = cronTime.GetValueOrDefault(utcNow) - utcNow;
|
|
|
|
if (delay < TimeSpan.Zero)
|
|
delay = TimeSpan.Zero;
|
|
|
|
if (!cronTime.HasValue) {
|
|
logger.LogError("Cron expression falied, falling back to default delay");
|
|
delay = TimeSpan.FromHours(12);
|
|
}
|
|
|
|
var nextRun = DateTime.Now + delay;
|
|
logger.LogInformation("Next backup run: {time}", nextRun.ToString("f"));
|
|
await Task.Delay(delay, stoppingToken);
|
|
|
|
await RunBackup(nextRun, stoppingToken);
|
|
}
|
|
}
|
|
|
|
private async Task RunBackup(DateTime optimalTime, CancellationToken stoppingToken) {
|
|
logger.LogInformation("Starting backup at {now}", DateTime.Now.ToString("f"));
|
|
|
|
var file = await CreateBackupArchive(optimalTime, stoppingToken);
|
|
if (string.IsNullOrEmpty(file)) {
|
|
logger.LogError("Backup archive creation failed");
|
|
return;
|
|
}
|
|
|
|
logger.LogInformation("Backup archive created, starting upload...");
|
|
|
|
var uploadResult = await client.UploadFile(file, stoppingToken);
|
|
if (!uploadResult.UploadSucceeded) {
|
|
logger.LogError("Upload failed");
|
|
File.Delete(file);
|
|
return;
|
|
}
|
|
|
|
logger.LogInformation("Upload completed");
|
|
|
|
File.Delete(file);
|
|
var count = await client.DeleteOldFiles(stoppingToken);
|
|
logger.LogInformation("Deleted {count} old backups", count);
|
|
|
|
logger.LogInformation("Backup completed");
|
|
}
|
|
|
|
private async Task<string> CreateBackupArchive(DateTime optimalTime, CancellationToken stoppingToken) {
|
|
var timestamp = optimalTime.ToString("yyyyMMdd_HHmmss");
|
|
var output = $"/tmp/backup_{timestamp}.tar.gz";
|
|
|
|
var process = new Process {
|
|
StartInfo = new ProcessStartInfo {
|
|
FileName = "tar",
|
|
ArgumentList = {
|
|
"-czf",
|
|
output,
|
|
"-C",
|
|
config.LocalRoot,
|
|
"-T",
|
|
Path.GetRelativePath(config.LocalRoot, config.IncludeFile)
|
|
},
|
|
RedirectStandardOutput = true,
|
|
RedirectStandardError = true
|
|
}
|
|
};
|
|
|
|
process.Start();
|
|
await process.WaitForExitAsync(stoppingToken);
|
|
|
|
if (process.ExitCode != 0) {
|
|
return string.Empty;
|
|
}
|
|
|
|
return output;
|
|
}
|
|
} |