using System.Text.Json; namespace JournalBot.Shared; public sealed record QueueStatus(int Pending, int Failed); public sealed class RuntimeReader { private readonly string _root; public RuntimeReader(string runtimeRoot) => _root = runtimeRoot; private string Queue(string sub) => Path.Combine(_root, "queue", sub); public IReadOnlyList ReadHistory() { var dir = Queue("done"); if (!Directory.Exists(dir)) return Array.Empty(); var items = new List(); foreach (var f in Directory.EnumerateFiles(dir, "*.json")) { try { var item = JsonSerializer.Deserialize( File.ReadAllText(f, System.Text.Encoding.UTF8)); if (item is not null) items.Add(item); } catch (JsonException) { /* skip malformed */ } } // Newest first by processed_at (fallback received_at). return items .OrderByDescending(i => i.ProcessedAt ?? i.ReceivedAt, StringComparer.Ordinal) .ToList(); } public QueueStatus ReadStatus() { int Count(string sub) => Directory.Exists(Queue(sub)) ? Directory.EnumerateFiles(Queue(sub), "*.json").Count() : 0; return new QueueStatus(Count("pending"), Count("failed")); } public IReadOnlyList TailLog(string fileName, int lines) { var path = Path.Combine(_root, "logs", fileName); if (!File.Exists(path)) return Array.Empty(); var all = File.ReadAllLines(path, System.Text.Encoding.UTF8); return all.Length <= lines ? all : all[^lines..]; } }