feat(assets): dynamic settings, IFinlyticLogger, live log streaming, and EF migration
This commit is contained in:
@@ -1,7 +1,13 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using FinlyticAssets.Models;
|
||||
using FinlyticAssets.Util;
|
||||
using FinlyticCore.Services;
|
||||
|
||||
namespace FinlyticAssets.Services;
|
||||
|
||||
@@ -13,8 +19,6 @@ public interface IAssetsIndexService
|
||||
/// <summary>
|
||||
/// Recreates the index file containing basic asset identifiers (ISIN and Name) for all active, valid assets.
|
||||
/// </summary>
|
||||
/// <param name="cancellationToken">A token to monitor for cancellation requests.</param>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
public Task ReCreateIndexFileAsync(CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
@@ -28,18 +32,13 @@ public interface IAssetsIndexService
|
||||
/// </summary>
|
||||
public class AssetsIndexService : IAssetsIndexService
|
||||
{
|
||||
private readonly ILogger<AssetsIndexService> _logger;
|
||||
private readonly IFinlyticLogger<AssetsIndexService> _finlyticLogger;
|
||||
private readonly IAssetsDbService _assetsDbService;
|
||||
private static readonly HttpClient _httpClient = new();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AssetsIndexService"/> class.
|
||||
/// </summary>
|
||||
/// <param name="logger">The logger for documenting indexing events and errors.</param>
|
||||
/// <param name="assetsDbService">The database service to query the assets from.</param>
|
||||
public AssetsIndexService(ILogger<AssetsIndexService> logger, IAssetsDbService assetsDbService)
|
||||
public AssetsIndexService(IFinlyticLogger<AssetsIndexService> finlyticLogger, IAssetsDbService assetsDbService)
|
||||
{
|
||||
_logger = logger;
|
||||
_finlyticLogger = finlyticLogger;
|
||||
_assetsDbService = assetsDbService;
|
||||
}
|
||||
|
||||
@@ -51,7 +50,7 @@ public class AssetsIndexService : IAssetsIndexService
|
||||
var assets = await _assetsDbService.GetAllValidAssetsAsync();
|
||||
if (assets == null || !assets.Any())
|
||||
{
|
||||
_logger.LogWarning("[{Channel}] No valid assets found in the database to index.", "AssetsChannel");
|
||||
await _finlyticLogger.LogWarningAsync(SettingKeys.AssetsChannel, "[AssetsIndexService] No valid assets found in the database to index.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -59,7 +58,6 @@ public class AssetsIndexService : IAssetsIndexService
|
||||
.DistinctBy(a => a.Isin)
|
||||
.Select(a => {
|
||||
string cleanIsin = a.Isin.Trim().ToUpperInvariant();
|
||||
// Point directly to our own local backend logo endpoint
|
||||
string imageUrl = $"/api/v1/logo/{cleanIsin}";
|
||||
return new AssetIndex(cleanIsin, a.Name, imageUrl);
|
||||
}).ToList();
|
||||
@@ -78,22 +76,22 @@ public class AssetsIndexService : IAssetsIndexService
|
||||
await JsonSerializer.SerializeAsync(fileStream, indexAssets, cancellationToken: cancellationToken);
|
||||
}
|
||||
|
||||
_logger.LogInformation("[{Channel}] Successfully recreated asset index file with {Count} entries pointing to local logos at {Path}",
|
||||
"AssetsChannel", indexAssets.Count, filePath);
|
||||
await _finlyticLogger.LogInfoAsync(SettingKeys.AssetsChannel, "[AssetsIndexService] Successfully recreated asset index file with {Count} entries pointing to local logos at {Path}",
|
||||
indexAssets.Count, filePath);
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
_logger.LogError(ex, "[{Channel}] Disk I/O error occurred while writing the asset index file.", "AssetsChannel");
|
||||
await _finlyticLogger.LogErrorAsync(SettingKeys.AssetsChannel, ex, "[AssetsIndexService] Disk I/O error occurred while writing the asset index file.");
|
||||
throw;
|
||||
}
|
||||
catch (JsonException ex)
|
||||
{
|
||||
_logger.LogError(ex, "[{Channel}] Failed to serialize the asset index data to JSON.", "AssetsChannel");
|
||||
await _finlyticLogger.LogErrorAsync(SettingKeys.AssetsChannel, ex, "[AssetsIndexService] Failed to serialize the asset index data to JSON.");
|
||||
throw;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "[{Channel}] An unexpected error occurred while recreating the asset index file.", "AssetsChannel");
|
||||
await _finlyticLogger.LogErrorAsync(SettingKeys.AssetsChannel, ex, "[AssetsIndexService] An unexpected error occurred while recreating the asset index file.");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
@@ -131,13 +129,13 @@ public class AssetsIndexService : IAssetsIndexService
|
||||
{
|
||||
byte[] data = await response.Content.ReadAsByteArrayAsync(cancellationToken);
|
||||
await File.WriteAllBytesAsync(filePath, data, cancellationToken);
|
||||
_logger.LogInformation("[{Channel}] Successfully saved logo SVG for ISIN {Isin} to {Path} on demand", "AssetsChannel", cleanIsin, filePath);
|
||||
await _finlyticLogger.LogInfoAsync(SettingKeys.AssetsChannel, "[AssetsIndexService] Successfully saved logo SVG for ISIN {Isin} to {Path} on demand", cleanIsin, filePath);
|
||||
return filePath;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "[{Channel}] Failed to download logo for ISIN {Isin} from {Url}", "AssetsChannel", cleanIsin, targetUrl);
|
||||
await _finlyticLogger.LogWarningAsync(SettingKeys.AssetsChannel, ex, "[AssetsIndexService] Failed to download logo for ISIN {Isin} from {Url}", cleanIsin, targetUrl);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user