From 2c7c643fdb46e02e7a0dc75507133a581c04369c Mon Sep 17 00:00:00 2001 From: Richard Date: Tue, 7 Jul 2026 09:21:37 +0200 Subject: [PATCH] Fix styling, job endpoints, and infinite worker loops --- src/Predictalytics.Api/wwwroot/css/style.css | 2 +- .../Services/EmbeddedWebServer.cs | 1 + .../Services/TradeHistoryWorker.cs | 7 +++++-- .../Services/TraderAnalyticsWorker.cs | 18 ++++++++++++------ 4 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/Predictalytics.Api/wwwroot/css/style.css b/src/Predictalytics.Api/wwwroot/css/style.css index 0b145c1..2b7c16d 100644 --- a/src/Predictalytics.Api/wwwroot/css/style.css +++ b/src/Predictalytics.Api/wwwroot/css/style.css @@ -444,7 +444,7 @@ body { .menubar-divider { width: 1px; height: 24px; background: var(--border); } .btn-outline { background: var(--bg-input); color: var(--text); border: 1px solid var(--border); border-radius: 6px; cursor: pointer; font-weight: 500; transition: all 0.2s; } .btn-outline:hover { background: var(--border); } -.btn-primary { background: var(--primary); color: #000; border: none; border-radius: 6px; cursor: pointer; font-weight: bold; transition: all 0.2s; } +.btn-primary { background: var(--accent); color: #fff; border: none; border-radius: 6px; cursor: pointer; font-weight: bold; transition: all 0.2s; } .btn-primary:hover { filter: brightness(1.1); } .tabs-nav { display: flex; gap: 12px; margin-bottom: 24px; border-bottom: 1px solid var(--border); padding-bottom: 8px; flex-wrap: wrap; align-items: center; } .btn-tab { diff --git a/src/Predictalytics.WinFormsHost/Services/EmbeddedWebServer.cs b/src/Predictalytics.WinFormsHost/Services/EmbeddedWebServer.cs index 3392a71..14a0c4a 100644 --- a/src/Predictalytics.WinFormsHost/Services/EmbeddedWebServer.cs +++ b/src/Predictalytics.WinFormsHost/Services/EmbeddedWebServer.cs @@ -77,6 +77,7 @@ public class EmbeddedWebServer app.MapMarketEndpoints(); app.MapAlertEndpoints(); app.MapSearchEndpoints(); + app.MapJobEndpoints(); app.MapGet("/api/health", () => Results.Ok(new { Status = "OK", Timestamp = DateTime.UtcNow })); await Predictalytics.Infrastructure.DependencyInjection.EnsureDatabaseAsync(app.Services, DbConnectionDebug); diff --git a/src/Predictalytics.Worker/Services/TradeHistoryWorker.cs b/src/Predictalytics.Worker/Services/TradeHistoryWorker.cs index 7544ab6..7b223a1 100644 --- a/src/Predictalytics.Worker/Services/TradeHistoryWorker.cs +++ b/src/Predictalytics.Worker/Services/TradeHistoryWorker.cs @@ -34,9 +34,9 @@ public class TradeHistoryWorker : BackgroundService while (!stoppingToken.IsCancellationRequested) { + IReadOnlyList tradersToProcess = new List(); try { - IReadOnlyList tradersToProcess = new List(); Domain.Entities.BackgroundJob? activeJob = null; using (var scope = _services.CreateScope()) @@ -260,7 +260,10 @@ public class TradeHistoryWorker : BackgroundService } catch (Exception ex) { _logger.LogError(ex, "TradeHistoryWorker error"); } - await Task.Delay(TimeSpan.FromMinutes(2), stoppingToken); + if (tradersToProcess == null || tradersToProcess.Count == 0) + { + await Task.Delay(TimeSpan.FromMinutes(2), stoppingToken); + } } _logger.LogInformation("📜 TradeHistoryWorker stopped"); diff --git a/src/Predictalytics.Worker/Services/TraderAnalyticsWorker.cs b/src/Predictalytics.Worker/Services/TraderAnalyticsWorker.cs index 510a968..83daf29 100644 --- a/src/Predictalytics.Worker/Services/TraderAnalyticsWorker.cs +++ b/src/Predictalytics.Worker/Services/TraderAnalyticsWorker.cs @@ -27,19 +27,22 @@ public class TraderAnalyticsWorker : BackgroundService { try { - await RunAnalyticsAsync(ct); + var processedCount = await RunAnalyticsAsync(ct); + if (processedCount == 0) + { + _logger.LogInformation("TraderAnalyticsWorker sleeping for 1 minute..."); + await Task.Delay(TimeSpan.FromMinutes(1), ct); + } } catch (Exception ex) { _logger.LogError(ex, "Error in TraderAnalyticsWorker"); + await Task.Delay(TimeSpan.FromMinutes(1), ct); } - - _logger.LogInformation("TraderAnalyticsWorker sleeping for 2 hours..."); - await Task.Delay(TimeSpan.FromHours(2), ct); } } - private async Task RunAnalyticsAsync(CancellationToken ct) + private async Task RunAnalyticsAsync(CancellationToken ct) { List traderIds = new List(); Domain.Entities.BackgroundJob? activeJob = null; @@ -104,8 +107,9 @@ public class TraderAnalyticsWorker : BackgroundService scoreObj.CalculatedAt = DateTime.UtcNow; trader.CurrentScore = scoreObj; - await traderRepo.UpdateAsync(trader, ct); } + trader.LastAnalyzedAt = DateTime.UtcNow; + await traderRepo.UpdateAsync(trader, ct); } if (activeJob != null && activeJob.TraderId == id) @@ -138,5 +142,7 @@ public class TraderAnalyticsWorker : BackgroundService { _logger.LogInformation("Trader analytics update complete."); } + + return traderIds.Count; } }