90 lines
3.0 KiB
C#
90 lines
3.0 KiB
C#
using System.Diagnostics;
|
|
using Cronos;
|
|
using OneDriveBackupService.Models;
|
|
using OneDriveBackupService.OneDrive;
|
|
|
|
namespace OneDriveBackupService;
|
|
|
|
public class Worker(ILogger<Worker> logger, ConfigData config, OneDriveClient client) : BackgroundService {
|
|
protected override async Task ExecuteAsync(CancellationToken stoppingToken) {
|
|
if (Environment.GetCommandLineArgs().Contains("--run-once")) {
|
|
logger.LogInformation("Manual backup triggered");
|
|
await RunBackup(DateTime.Now, stoppingToken);
|
|
Environment.Exit(0);
|
|
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 failed, falling back to default delay");
|
|
delay = TimeSpan.FromHours(12);
|
|
}
|
|
|
|
var nextRun = DateTime.Now + delay;
|
|
logger.LogInformation("Next backup: {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;
|
|
}
|
|
|
|
client.UploadFile(file);
|
|
|
|
var count = client.DeleteOldFiles();
|
|
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.Combine(config.LocalRoot, config.IncludeFile)
|
|
},
|
|
RedirectStandardOutput = true,
|
|
RedirectStandardError = true
|
|
}
|
|
};
|
|
|
|
process.Start();
|
|
await process.WaitForExitAsync(stoppingToken);
|
|
|
|
if (process.ExitCode != 0) {
|
|
var error = await process.StandardError.ReadToEndAsync(stoppingToken);
|
|
logger.LogError(error);
|
|
|
|
return string.Empty;
|
|
}
|
|
|
|
return output;
|
|
}
|
|
} |