Phase 1: Modul-System formalisiert (IModule + ModuleRegistry)

- Core/Modules/IModule.cs: Vertrag (Key, DisplayName, Description, Version,
  RegisterServices, InitializeAsync, GetWorkers, CreateWindow)
- Core/Modules/ModuleRegistry.cs
- CongressTradingModule auf IModule umgestellt (instanzbasiert, Platzhalter-Fenster)
- Program.cs iteriert ueber IModule[] + Registry; Form1 initialisiert Module ueber Registry
- Testbarkeit: WorkerBase DB-Log-Seam (virtuell); CapitolTradesScraper.ParseTradesFromHtml
  extrahiert (offline gegen ct_raw.html testbar)
- Tests: ModuleRegistry, CongressTradingModule, WorkerBase, CapitolTradesScraper -> 15/15 gruen

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@
This commit is contained in:
Richard
2026-07-27 10:07:47 +02:00
parent 9abad277c2
commit af398353f0
13 changed files with 449 additions and 35 deletions
+14 -4
View File
@@ -126,9 +126,9 @@ public abstract class WorkerBase : IWorker
try
{
logId = await Db.BeginWorkerLogAsync(Name, Module);
logId = await BeginRunLogAsync();
await ExecuteAsync(ct);
await Db.EndWorkerLogAsync(logId, true);
await EndRunLogAsync(logId, true);
Info.LastRuntime = DateTime.Now;
Info.Status = WorkerStatus.Idle;
@@ -137,20 +137,30 @@ public abstract class WorkerBase : IWorker
catch (OperationCanceledException)
{
if (logId > 0)
await Db.EndWorkerLogAsync(logId, false, "Abgebrochen");
await EndRunLogAsync(logId, false, "Abgebrochen");
Info.Status = WorkerStatus.Stopped;
Info.Info = "Abgebrochen";
}
catch (Exception ex)
{
if (logId > 0)
await Db.EndWorkerLogAsync(logId, false, ex.Message);
await EndRunLogAsync(logId, false, ex.Message);
Logger.Error(Module, $"Fehler in Worker {Name}: {ex.Message}", ex);
Info.Status = WorkerStatus.Error;
Info.Info = $"Fehler: {ex.Message}";
}
}
// ─── DB-Log-Seam (überschreibbar für Unit-Tests) ──────────────────────────
/// <summary>Legt den Worker-Log-Eintrag an. Kapselt den DB-Zugriff (testbar).</summary>
protected virtual Task<long> BeginRunLogAsync()
=> Db.BeginWorkerLogAsync(Name, Module);
/// <summary>Schließt den Worker-Log-Eintrag ab. Kapselt den DB-Zugriff (testbar).</summary>
protected virtual Task EndRunLogAsync(long logId, bool success, string? message = null)
=> Db.EndWorkerLogAsync(logId, success, message);
// ─── Hilfsmethoden ────────────────────────────────────────────────────────
private static string FormatInterval(TimeSpan ts)