Fix: Implement FixPlan part A9, A10, B

This commit is contained in:
Richard
2026-07-10 12:04:27 +02:00
parent 44f48284a2
commit 1787422243
28 changed files with 1025 additions and 79 deletions
@@ -31,6 +31,13 @@ public class TradeHistoryWorker : BackgroundService
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
_logger.LogInformation("📜 TradeHistoryWorker started (update cooldown: {Hours}h)", CooldownHours);
using (var scope = _services.CreateScope())
{
var jobRepo = scope.ServiceProvider.GetRequiredService<IJobRepository>();
await jobRepo.ResetHungJobsAsync(stoppingToken);
}
await Task.Delay(15000, stoppingToken);
while (!stoppingToken.IsCancellationRequested)
@@ -43,7 +50,11 @@ public class TradeHistoryWorker : BackgroundService
using (var scope = _services.CreateScope())
{
var jobRepo = scope.ServiceProvider.GetRequiredService<IJobRepository>();
activeJob = await jobRepo.GetNextPendingJobAsync(Predictalytics.Domain.Enums.JobType.HistorySync, stoppingToken);
activeJob = await jobRepo.GetNextPendingJobAsync(Predictalytics.Domain.Enums.JobType.DeepResync, stoppingToken);
if (activeJob == null)
{
activeJob = await jobRepo.GetNextPendingJobAsync(Predictalytics.Domain.Enums.JobType.HistorySync, stoppingToken);
}
var repo = scope.ServiceProvider.GetRequiredService<ITraderRepository>();
@@ -109,12 +120,35 @@ public class TradeHistoryWorker : BackgroundService
using var platformCtx = PlatformLogContext.Push(provider.PlatformName);
await rateLimiter.WaitAsync(trader.Platform, ct);
bool isInitial = !trader.IsInitialImportComplete;
_logger.LogInformation("{Trader}: Starting {Type} sync", trader.DisplayName, isInitial ? "INITIAL FULL" : "INCREMENTAL");
bool isDeepResync = activeJob != null && activeJob.JobType == Predictalytics.Domain.Enums.JobType.DeepResync;
bool isInitial = !trader.IsInitialImportComplete || isDeepResync;
_logger.LogInformation("{Trader}: Starting {Type} sync", trader.DisplayName, isDeepResync ? "DEEP RESYNC" : (isInitial ? "INITIAL FULL" : "INCREMENTAL"));
var fetchedTrades = await provider.GetTraderTradesAsync(trader.PlatformUserId, TradesPerFetch, ct);
if (isDeepResync)
{
var db = scope.ServiceProvider.GetRequiredService<Predictalytics.Infrastructure.Data.AppDbContext>();
await Microsoft.EntityFrameworkCore.RelationalDatabaseFacadeExtensions.ExecuteSqlRawAsync(db.Database, "DELETE FROM Trades WHERE TraderId = {0} AND PlatformTradeId LIKE 'COMPACT_%'", t.Id);
await Microsoft.EntityFrameworkCore.RelationalDatabaseFacadeExtensions.ExecuteSqlRawAsync(db.Database, "DELETE FROM TraderPositions WHERE TraderId = {0}", t.Id);
}
IReadOnlyList<Domain.Entities.Trade> fetchedTrades;
if (isDeepResync)
{
fetchedTrades = await provider.GetTradesPagedAsync(trader.PlatformUserId, 500, ct);
}
else
{
fetchedTrades = await provider.GetTraderTradesAsync(trader.PlatformUserId, TradesPerFetch, ct);
}
var validTrades = fetchedTrades.Where(tr => !string.IsNullOrWhiteSpace(tr.PlatformTradeId)).ToList();
var updatedName = validTrades.FirstOrDefault(t => !string.IsNullOrEmpty(t.TransientDisplayName))?.TransientDisplayName;
if (!string.IsNullOrEmpty(updatedName) && !string.Equals(trader.DisplayName, updatedName, StringComparison.OrdinalIgnoreCase))
{
trader.DisplayName = updatedName;
await traderRepo.UpdateAsync(trader, ct);
}
var fetchedTradeIds = validTrades.Select(tr => tr.PlatformTradeId).ToList();
var knownTradeIds = await tradeRepo.GetKnownPlatformTradeIdsAsync(trader.Platform, trader.Id, fetchedTradeIds, ct);
@@ -230,6 +264,7 @@ public class TradeHistoryWorker : BackgroundService
trader.IsInitialImportComplete = true;
trader.LastTradesUpdatedAt = DateTime.UtcNow;
trader.LastPolledAt = DateTime.UtcNow;
if (isDeepResync) trader.LastAnalyzedAt = null;
await traderRepo.UpdateAsync(trader, ct);
if (activeJob != null && activeJob.TraderId == trader.Id)