feat(assets): dynamic settings, IFinlyticLogger, live log streaming, and EF migration
This commit is contained in:
@@ -6,9 +6,9 @@ using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using FinlyticAssets.Util;
|
||||
using FinlyticCore.Services;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace FinlyticAssets.Services;
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace FinlyticAssets.Services;
|
||||
/// </summary>
|
||||
public class LogoFetcherBackgroundService : BackgroundService
|
||||
{
|
||||
private readonly ILogger<LogoFetcherBackgroundService> _logger;
|
||||
private readonly IFinlyticLogger<LogoFetcherBackgroundService> _finlyticLogger;
|
||||
private readonly IServiceScopeFactory _scopeFactory;
|
||||
private readonly HttpClient _httpClient;
|
||||
|
||||
@@ -32,10 +32,10 @@ public class LogoFetcherBackgroundService : BackgroundService
|
||||
""";
|
||||
|
||||
public LogoFetcherBackgroundService(
|
||||
ILogger<LogoFetcherBackgroundService> logger,
|
||||
IFinlyticLogger<LogoFetcherBackgroundService> finlyticLogger,
|
||||
IServiceScopeFactory scopeFactory)
|
||||
{
|
||||
_logger = logger;
|
||||
_finlyticLogger = finlyticLogger;
|
||||
_scopeFactory = scopeFactory;
|
||||
_httpClient = new HttpClient();
|
||||
_httpClient.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36");
|
||||
@@ -45,7 +45,7 @@ public class LogoFetcherBackgroundService : BackgroundService
|
||||
|
||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
_logger.LogInformation("[{Channel}] LogoFetcherBackgroundService started. Will fetch missing logos periodically.", "AssetsChannel");
|
||||
await _finlyticLogger.LogInfoAsync(SettingKeys.AssetsChannel, "[LogoFetcherBackgroundService] LogoFetcherBackgroundService started. Will fetch missing logos periodically.");
|
||||
|
||||
await Task.Delay(TimeSpan.FromSeconds(10), stoppingToken);
|
||||
|
||||
@@ -57,7 +57,7 @@ public class LogoFetcherBackgroundService : BackgroundService
|
||||
}
|
||||
catch (Exception ex) when (!stoppingToken.IsCancellationRequested)
|
||||
{
|
||||
_logger.LogError(ex, "[{Channel}] Error occurred while executing logo batch fetch.", "AssetsChannel");
|
||||
await _finlyticLogger.LogErrorAsync(SettingKeys.AssetsChannel, ex, "[LogoFetcherBackgroundService] Error occurred while executing logo batch fetch.");
|
||||
}
|
||||
|
||||
try
|
||||
@@ -70,7 +70,7 @@ public class LogoFetcherBackgroundService : BackgroundService
|
||||
}
|
||||
}
|
||||
|
||||
_logger.LogInformation("[{Channel}] LogoFetcherBackgroundService stopped.", "AssetsChannel");
|
||||
await _finlyticLogger.LogInfoAsync(SettingKeys.AssetsChannel, "[LogoFetcherBackgroundService] LogoFetcherBackgroundService stopped.");
|
||||
}
|
||||
|
||||
private async Task ProcessMissingLogosBatchAsync(CancellationToken stoppingToken)
|
||||
@@ -88,7 +88,6 @@ public class LogoFetcherBackgroundService : BackgroundService
|
||||
Directory.CreateDirectory(directoryPath);
|
||||
}
|
||||
|
||||
// ✅ Prüft sowohl DB-Eintrag ALS AUCH, ob die Datei bereits lokal existiert
|
||||
var missingIsins = validAssets
|
||||
.Select(a => a.Isin?.Trim().ToUpperInvariant())
|
||||
.Where(isin => !string.IsNullOrEmpty(isin))
|
||||
@@ -98,12 +97,12 @@ public class LogoFetcherBackgroundService : BackgroundService
|
||||
|
||||
if (missingIsins.Count == 0)
|
||||
{
|
||||
_logger.LogDebug("All asset logos are downloaded and up to date.");
|
||||
await _finlyticLogger.LogDebugAsync(SettingKeys.AssetsChannel, "[LogoFetcherBackgroundService] All asset logos are downloaded and up to date.");
|
||||
return;
|
||||
}
|
||||
|
||||
var batchToFetch = missingIsins.Take(60).ToList();
|
||||
_logger.LogInformation("[{Channel}] Found {Count} missing logos on disk. Fetching bulk batch of {BatchSize} logos...", "AssetsChannel", missingIsins.Count, batchToFetch.Count);
|
||||
await _finlyticLogger.LogInfoAsync(SettingKeys.AssetsChannel, "[LogoFetcherBackgroundService] Found {Count} missing logos on disk. Fetching bulk batch of {BatchSize} logos...", missingIsins.Count, batchToFetch.Count);
|
||||
|
||||
int successCount = 0;
|
||||
|
||||
@@ -126,7 +125,7 @@ public class LogoFetcherBackgroundService : BackgroundService
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogWarning("[{Channel}] Logo not found on CDN for ISIN {Isin} (HTTP {StatusCode}). Saving SVG placeholder.", "AssetsChannel", isin, response.StatusCode);
|
||||
await _finlyticLogger.LogWarningAsync(SettingKeys.AssetsChannel, "[LogoFetcherBackgroundService] Logo not found on CDN for ISIN {Isin} (HTTP {StatusCode}). Saving SVG placeholder.", isin, response.StatusCode);
|
||||
byte[] placeholderData = Encoding.UTF8.GetBytes(PlaceholderSvg);
|
||||
await File.WriteAllBytesAsync(filePath, placeholderData, stoppingToken);
|
||||
successCount++;
|
||||
@@ -136,7 +135,7 @@ public class LogoFetcherBackgroundService : BackgroundService
|
||||
}
|
||||
catch (Exception ex) when (!stoppingToken.IsCancellationRequested)
|
||||
{
|
||||
_logger.LogWarning(ex, "[{Channel}] Exception while downloading logo for ISIN {Isin} from {Url}. Saving SVG placeholder.", "AssetsChannel", isin, targetUrl);
|
||||
await _finlyticLogger.LogWarningAsync(SettingKeys.AssetsChannel, ex, "[LogoFetcherBackgroundService] Exception while downloading logo for ISIN {Isin} from {Url}. Saving SVG placeholder.", isin, targetUrl);
|
||||
try
|
||||
{
|
||||
byte[] placeholderData = Encoding.UTF8.GetBytes(PlaceholderSvg);
|
||||
@@ -148,23 +147,22 @@ public class LogoFetcherBackgroundService : BackgroundService
|
||||
catch { }
|
||||
}
|
||||
|
||||
// Kurze Pause gegen Rate Limiting
|
||||
await Task.Delay(50, stoppingToken);
|
||||
}
|
||||
|
||||
_logger.LogInformation("[{Channel}] Batch fetch complete. Successfully processed {SuccessCount}/{BatchSize} logos. Remaining missing: {Remaining}",
|
||||
"AssetsChannel", successCount, batchToFetch.Count, missingIsins.Count - batchToFetch.Count);
|
||||
await _finlyticLogger.LogInfoAsync(SettingKeys.AssetsChannel, "[LogoFetcherBackgroundService] Batch fetch complete. Successfully processed {SuccessCount}/{BatchSize} logos. Remaining missing: {Remaining}",
|
||||
successCount, batchToFetch.Count, missingIsins.Count - batchToFetch.Count);
|
||||
|
||||
if (successCount > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
await indexService.ReCreateIndexFileAsync(stoppingToken);
|
||||
_logger.LogInformation("[{Channel}] Successfully updated index.json after logo batch fetch.", "AssetsChannel");
|
||||
await _finlyticLogger.LogInfoAsync(SettingKeys.AssetsChannel, "[LogoFetcherBackgroundService] Successfully updated index.json after logo batch fetch.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "[{Channel}] Failed to update index.json after logo batch fetch.", "AssetsChannel");
|
||||
await _finlyticLogger.LogWarningAsync(SettingKeys.AssetsChannel, ex, "[LogoFetcherBackgroundService] Failed to update index.json after logo batch fetch.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user