Compare commits

..

2 Commits

Author SHA1 Message Date
523441dd2f extra logging 2025-12-17 00:15:43 -05:00
6e91d188fe ensure proper disposal of objects 2025-12-17 00:15:23 -05:00

View File

@@ -10,26 +10,36 @@ using Serilog.Events;
var resetEvent = new ManualResetEvent(false); var resetEvent = new ManualResetEvent(false);
using var tokenSource = new CancellationTokenSource(); using var tokenSource = new CancellationTokenSource();
Console.CancelKeyPress += (sender, eventArgs) => Console.CancelKeyPress += (_, eventArgs) =>
{ {
resetEvent?.Set(); Log.Debug("Canceling with CancelKeyPress");
tokenSource?.Cancel(); Dispose();
eventArgs.Cancel = true; eventArgs.Cancel = true;
Log.CloseAndFlush();
}; };
AppDomain.CurrentDomain.ProcessExit += (_, _) => Dispose();
SetupLogging(); SetupLogging();
//TODO: check environment variables to see if config file is enabled, otherwise use env vars
var config = LoadConfig(); var config = LoadConfig();
Log.Information("Configuration file loaded. Beginning initial grab."); Log.Information("Configuration file loaded. Beginning initial grab.");
await RunJob(config, tokenSource.Token); await RunJob(config, tokenSource.Token);
Log.Information("Initial grab complete. Initializing schedule."); Log.Information("Initial grab complete. Initializing schedule.");
Task.Run(() => ScheduleJobs(config, tokenSource.Token)); Task.Run(() => ScheduleJobs(config, tokenSource.Token));
Log.Verbose("Jobs scheduled. Main Thread waiting.");
resetEvent.WaitOne(); resetEvent.WaitOne();
return; return;
void Dispose()
{
resetEvent?.Set();
tokenSource?.Cancel();
Log.CloseAndFlush();
}
static void SetupLogging() static void SetupLogging()
{ {
var minLevel = (Environment.GetEnvironmentVariable("LOG_LEVEL") ?? "info").ToUpperInvariant() switch var minLevel = (Environment.GetEnvironmentVariable("LOG_LEVEL") ?? "info").ToUpperInvariant() switch
@@ -63,13 +73,14 @@ static Config LoadConfig()
WriteIndented = true WriteIndented = true
}; };
//TODO: stop creating dummy config file
if (!File.Exists("/config.json")) if (!File.Exists("/config.json"))
{ {
Log.Fatal("No config file found, creating dummy config."); Log.Fatal("No config file found, creating dummy config.");
CreateConfig(serializationOptions); CreateConfig(serializationOptions);
Environment.Exit(1); Environment.Exit(1);
} }
Log.Verbose("Loading config from file.");
var configFile = File.ReadAllText("/config.json"); var configFile = File.ReadAllText("/config.json");
return JsonSerializer.Deserialize<Config>(configFile, serializationOptions); return JsonSerializer.Deserialize<Config>(configFile, serializationOptions);
} }
@@ -84,6 +95,7 @@ static void CreateConfig(JsonSerializerOptions options)
static async Task ScheduleJobs(Config config, CancellationToken token) static async Task ScheduleJobs(Config config, CancellationToken token)
{ {
Log.Debug($"Scheduling job with cron expression '{config.Schedule}'");
var schedule = CronExpression.Parse(config.Schedule); var schedule = CronExpression.Parse(config.Schedule);
while (!token.IsCancellationRequested) while (!token.IsCancellationRequested)
@@ -95,11 +107,12 @@ static async Task ScheduleJobs(Config config, CancellationToken token)
Log.Information($"Next scheduled scan at {nextJob.Value}"); Log.Information($"Next scheduled scan at {nextJob.Value}");
var delay = nextJob.Value - now; var delay = nextJob.Value - now;
Log.Debug($"{delay} until next scan at {nextJob.Value}");
if (delay > TimeSpan.Zero) if (delay > TimeSpan.Zero)
{ {
await Task.Delay(delay, token); await Task.Delay(delay, token);
} }
Log.Debug($"Delay {delay} wait is complete, beginning scan now.");
await RunJob(config, token); await RunJob(config, token);
} }
} }
@@ -131,11 +144,13 @@ static async Task RecurseDirectory(SftpClient client, string source, string dest
if (item.IsDirectory) if (item.IsDirectory)
{ {
Log.Verbose($"{item.Name} is a directory");
var newPath = Path.Combine(destination, item.Name); var newPath = Path.Combine(destination, item.Name);
await RecurseDirectory(client, item.FullName, newPath, true, token); await RecurseDirectory(client, item.FullName, newPath, true, token);
return; return;
} }
Log.Verbose($"{item.Name} is a file");
await DownloadFile(client, item, destination, token); await DownloadFile(client, item, destination, token);
Log.Information($"Deleting '{item.Name}'"); Log.Information($"Deleting '{item.Name}'");
await client.DeleteAsync(item.FullName, token); await client.DeleteAsync(item.FullName, token);
@@ -151,9 +166,11 @@ static async Task RecurseDirectory(SftpClient client, string source, string dest
static async Task DownloadFile(SftpClient client, ISftpFile item, string destination, CancellationToken token) static async Task DownloadFile(SftpClient client, ISftpFile item, string destination, CancellationToken token)
{ {
Directory.CreateDirectory(destination); Directory.CreateDirectory(destination);
Log.Verbose($"Ensuring '{destination}' path exists.");
await using var stream = File.Open(Path.Combine(destination, item.Name), FileMode.Create, FileAccess.Write); await using var stream = File.Open(Path.Combine(destination, item.Name), FileMode.Create, FileAccess.Write);
Log.Information($"Downloading '{item.FullName}' to '{stream.Name}'"); Log.Information($"Downloading '{item.FullName}' to '{stream.Name}'");
await client.DownloadFileAsync(item.FullName, stream, token); await client.DownloadFileAsync(item.FullName, stream, token);
Log.Verbose("Download completed.");
} }
static SftpClient GetClient(SFtpTarget target) static SftpClient GetClient(SFtpTarget target)