journal-bot/tools/JournalBot.Service/Worker.cs

56 lines
2.0 KiB
C#

using JournalBot.Shared;
namespace JournalBot.Service;
public sealed class Worker : BackgroundService
{
private readonly ILogger<Worker> _log;
private readonly BotRunner _runner;
private readonly TimeSpan _interval;
private readonly string _serviceLogPath;
public Worker(ILogger<Worker> log, IConfiguration config)
{
_log = log;
var py = config["JournalBot:PythonExe"]!;
var workingDir = config["JournalBot:WorkingDir"]!;
var minutes = config.GetValue("JournalBot:IntervalMinutes", 15);
_runner = new BotRunner(py, workingDir);
_interval = TimeSpan.FromMinutes(minutes);
_serviceLogPath = Path.Combine(workingDir, "runtime", "logs", "service.log");
Directory.CreateDirectory(Path.GetDirectoryName(_serviceLogPath)!);
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
// Run once at startup, then every interval.
await RunIngestAsync(stoppingToken);
using var timer = new PeriodicTimer(_interval);
while (await timer.WaitForNextTickAsync(stoppingToken))
await RunIngestAsync(stoppingToken);
}
private async Task RunIngestAsync(CancellationToken ct)
{
try
{
var result = await _runner.RunAsync("ingest", ct);
var line = $"[{DateTimeOffset.Now:O}] ingest exit={result.ExitCode}";
_log.LogInformation("{Line}", line);
await AppendLogAsync(line + "\n" + result.Output);
}
catch (OperationCanceledException) { throw; }
catch (Exception ex)
{
_log.LogError(ex, "ingest run failed");
await AppendLogAsync($"[{DateTimeOffset.Now:O}] ingest ERROR: {ex.Message}");
}
}
private async Task AppendLogAsync(string text)
{
try { await File.AppendAllTextAsync(_serviceLogPath, text + "\n", System.Text.Encoding.UTF8); }
catch { /* logging must never crash the service */ }
}
}