using Dapper;
using GB5Shared.Connection;
using GB5Shared.Enums.ReportOrchestration;
using GB5Shared.Query.FrameWork.DbConnection;
using Microsoft.Data.SqlClient;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Npgsql;
using System.Data;
namespace FrameworkBLL.ReportOrchestration
{
///
/// Per-request cache of MSERVERCONFIG rows keyed by SERVERCONFIGID.
/// Loaded lazily from the system DB on first access; subsequent lookups
/// within the same HTTP request are served from the in-memory dictionary.
///
public sealed class ServerConfigCache : IServerConfigCache
{
private readonly IApplicationConnection _appConnection;
private readonly IConfiguration _configuration;
private readonly ILogger _logger;
private readonly Dictionary _cache = new();
public ServerConfigCache(
IApplicationConnection appConnection,
IConfiguration configuration,
ILogger logger)
{
_appConnection = appConnection;
_configuration = configuration;
_logger = logger;
}
public async Task GetAsync(
int serverConfigId,
CancellationToken cancellationToken = default)
{
if (_cache.TryGetValue(serverConfigId, out var cached))
return cached;
var row = await LoadFromSystemDbAsync(serverConfigId, cancellationToken)
.ConfigureAwait(false);
_cache[serverConfigId] = row;
return row;
}
private async Task LoadFromSystemDbAsync(
int serverConfigId,
CancellationToken cancellationToken)
{
string systemConnStr = await _appConnection.Gb5SystemConnectionString()
.ConfigureAwait(false);
int dbType = _configuration.GetValue("Gb5SystemDTO:DataBaseType", 0);
using IDbConnection conn = dbType switch
{
1 => new NpgsqlConnection(systemConnStr),
_ => new SqlConnection(systemConnStr)
};
var row = await conn.QueryFirstOrDefaultAsync(
ConnectionQueryBuilder.GET_MSERVERCONFIG_BY_ID,
new { ServerConfigId = serverConfigId }).ConfigureAwait(false);
if (row is null)
throw new InvalidOperationException(
$"MSERVERCONFIG row not found for ServerConfigId={serverConfigId}.");
string decryptedPwd = _appConnection.Decrypt(row.DatabasePassword, "GB5");
_logger.LogDebug(
"ServerConfigCache loaded ServerConfigId={Id} ProviderType={Provider}",
row.ServerConfigId, row.ProviderType);
return new CachedServerConfig
{
ServerConfigId = row.ServerConfigId,
ProviderType = (DatabaseProviderType)row.ProviderType,
DatabaseName = row.DatabaseName,
DatabaseUserName = row.DatabaseUserName,
DatabasePassword = decryptedPwd,
DatabasePort = row.DatabasePort,
ServerIp = row.ServerIp,
ServerMachineName = row.ServerMachineName,
ReportServerConfigId = row.ReportServerConfigId,
ArchiveServerConfigId = row.ArchiveServerConfigId,
Nature = row.Nature
};
}
// Dapper projection — internal only, not exposed outside this class
private sealed class RawServerConfig
{
public int ServerConfigId { get; init; }
public byte ProviderType { get; init; }
public string DatabaseName { get; init; } = string.Empty;
public string DatabaseUserName { get; init; } = string.Empty;
public string DatabasePassword { get; init; } = string.Empty;
public string DatabasePort { get; init; } = string.Empty;
public byte Nature { get; init; }
public int ReportServerConfigId { get; init; } = -1;
public int ArchiveServerConfigId { get; init; } = -1;
public string ServerIp { get; init; } = string.Empty;
public string ServerMachineName { get; init; } = string.Empty;
}
}
}