@
R3 Slice 3: CongressTrading-Modul + Worker-Log + core_settings auf EF Core - Modul: CongressTradingDbContext (ct_congressMember/ct_trade) + Design-Time-Factory; CongressRepository von Dapper auf EF; CongressTrade.DetailsFetched ergaenzt; Dapper entfernt - Core: CoreSettingsService (core_settings via EF); WorkerBase-Log auf EF (core_worker_log); 7 Worker-Ctors DatabaseService -> IDbContextFactory<CoreDbContext> - CoreMigrations + CongressMigrations (Dapper) entfernt; core_-Schema nun rein EF - EF-Migration InitialCongressTrading; AddCorePersistence-Fallback fuer leeren Connection-String (App startet ohne DB); Connection aus appsettings.Local.json (gitignored) - Tests: +4 CongressRepository (EF-InMemory) -> 39/39 gruen; Build + smoke-ui + App-Start ok Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> @
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
using IBKRTrader.Core.Persistence.Ef;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using IBKRTrader.Core.Database;
|
||||
using IBKRTrader.Core.Logging;
|
||||
using IBKRTrader.Core.Settings;
|
||||
@@ -21,7 +23,7 @@ public class BackupWorker : WorkerBase
|
||||
protected override TimeSpan? Interval =>
|
||||
TimeSpan.FromMinutes(_settings.Settings.WorkerSettings.BackupWorker.IntervalMinutes);
|
||||
|
||||
public BackupWorker(LoggingService logger, DatabaseService db, SettingsService settings)
|
||||
public BackupWorker(LoggingService logger, IDbContextFactory<CoreDbContext> db, SettingsService settings)
|
||||
: base(logger, db)
|
||||
{
|
||||
_settings = settings;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using IBKRTrader.Core.Persistence.Ef;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using IBKRTrader.Core.Database;
|
||||
using IBKRTrader.Core.IBKR;
|
||||
using IBKRTrader.Core.Logging;
|
||||
@@ -22,7 +24,7 @@ public class IBKRInstrumentSyncWorker : WorkerBase
|
||||
private readonly IBKRMarketDataRepository _repo;
|
||||
|
||||
public IBKRInstrumentSyncWorker(
|
||||
LoggingService logger, DatabaseService db,
|
||||
LoggingService logger, IDbContextFactory<CoreDbContext> db,
|
||||
SettingsService settings, IBKRGatewayService gateway,
|
||||
IBKRMarketDataRepository repo)
|
||||
: base(logger, db)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using IBKRTrader.Core.Persistence.Ef;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using IBKRTrader.Core.Database;
|
||||
using IBKRTrader.Core.IBKR;
|
||||
using IBKRTrader.Core.Logging;
|
||||
@@ -29,7 +31,7 @@ public class IBKRPriceHistoryWorker : WorkerBase
|
||||
private readonly IBKRMarketDataRepository _repo;
|
||||
|
||||
public IBKRPriceHistoryWorker(
|
||||
LoggingService logger, DatabaseService db,
|
||||
LoggingService logger, IDbContextFactory<CoreDbContext> db,
|
||||
SettingsService settings, IBKRGatewayService gateway,
|
||||
IBKRMarketDataRepository repo)
|
||||
: base(logger, db)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using IBKRTrader.Core.Persistence.Ef;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
@@ -27,7 +29,7 @@ public class WebApiService : WorkerBase
|
||||
|
||||
protected override TimeSpan? Interval => null;
|
||||
|
||||
public WebApiService(LoggingService logger, DatabaseService db, SettingsService settings)
|
||||
public WebApiService(LoggingService logger, IDbContextFactory<CoreDbContext> db, SettingsService settings)
|
||||
: base(logger, db)
|
||||
{
|
||||
_settings = settings;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using IBKRTrader.Core.Persistence.Ef;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using IBKRTrader.Core.Database;
|
||||
@@ -22,7 +24,7 @@ public class WebserverService : WorkerBase
|
||||
|
||||
protected override TimeSpan? Interval => null; // Service = permanent
|
||||
|
||||
public WebserverService(LoggingService logger, DatabaseService db, SettingsService settings)
|
||||
public WebserverService(LoggingService logger, IDbContextFactory<CoreDbContext> db, SettingsService settings)
|
||||
: base(logger, db)
|
||||
{
|
||||
_settings = settings;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using IBKRTrader.Core.Database;
|
||||
using IBKRTrader.Core.Logging;
|
||||
using IBKRTrader.Core.Persistence.Ef;
|
||||
using IBKRTrader.Core.Persistence.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace IBKRTrader.Core.Workers;
|
||||
|
||||
@@ -26,8 +28,8 @@ public abstract class WorkerBase : IWorker
|
||||
|
||||
// ─── Infrastruktur ────────────────────────────────────────────────────────
|
||||
|
||||
protected readonly LoggingService Logger;
|
||||
protected readonly DatabaseService Db;
|
||||
protected readonly LoggingService Logger;
|
||||
private readonly IDbContextFactory<CoreDbContext> _dbf;
|
||||
|
||||
public WorkerInfo Info { get; } = new();
|
||||
|
||||
@@ -35,10 +37,10 @@ public abstract class WorkerBase : IWorker
|
||||
private Task? _runLoop;
|
||||
private readonly SemaphoreSlim _triggerSemaphore = new(0, 1);
|
||||
|
||||
protected WorkerBase(LoggingService logger, DatabaseService db)
|
||||
protected WorkerBase(LoggingService logger, IDbContextFactory<CoreDbContext> dbf)
|
||||
{
|
||||
Logger = logger;
|
||||
Db = db;
|
||||
_dbf = dbf;
|
||||
|
||||
Info.WorkerName = Name;
|
||||
Info.Module = Module;
|
||||
@@ -153,13 +155,33 @@ public abstract class WorkerBase : IWorker
|
||||
|
||||
// ─── 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>Legt den Worker-Log-Eintrag an (core_worker_log via EF). Kapselt den DB-Zugriff (testbar).</summary>
|
||||
protected virtual async Task<long> BeginRunLogAsync()
|
||||
{
|
||||
await using var db = await _dbf.CreateDbContextAsync();
|
||||
var log = new CoreWorkerLog
|
||||
{
|
||||
WorkerName = Name,
|
||||
Module = Module,
|
||||
StartedAt = DateTime.UtcNow,
|
||||
Status = "Running"
|
||||
};
|
||||
db.WorkerLog.Add(log);
|
||||
await db.SaveChangesAsync();
|
||||
return log.Id;
|
||||
}
|
||||
|
||||
/// <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);
|
||||
protected virtual async Task EndRunLogAsync(long logId, bool success, string? message = null)
|
||||
{
|
||||
await using var db = await _dbf.CreateDbContextAsync();
|
||||
var log = await db.WorkerLog.FindAsync(logId);
|
||||
if (log is null) return;
|
||||
log.FinishedAt = DateTime.UtcNow;
|
||||
log.Status = success ? "Success" : "Error";
|
||||
log.Message = message;
|
||||
await db.SaveChangesAsync();
|
||||
}
|
||||
|
||||
// ─── Hilfsmethoden ────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
Reference in New Issue
Block a user