95 lines
3.6 KiB
C#
95 lines
3.6 KiB
C#
using Microsoft.Extensions.Logging;
|
|
using PARR.DAL.CacheServices;
|
|
using PARR.DAL.DomainServices.Interfaces;
|
|
using PARR.DAL.Settings;
|
|
using System.Security.Cryptography;
|
|
using System.Text;
|
|
|
|
namespace PARR.DAL.DomainServices.Implementations
|
|
{
|
|
public class GroupedShortcodesCacheService : IGroupedShortcodesCacheService
|
|
{
|
|
private readonly IRedisCacheService cacheService;
|
|
private readonly GroupedShortcodesCacheSettings settings;
|
|
private readonly ILogger<GroupedShortcodesCacheService> logger;
|
|
|
|
public GroupedShortcodesCacheService(
|
|
IRedisCacheService cacheService,
|
|
GroupedShortcodesCacheSettings settings,
|
|
ILogger<GroupedShortcodesCacheService> logger)
|
|
{
|
|
this.cacheService = cacheService;
|
|
this.settings = settings;
|
|
this.logger = logger;
|
|
}
|
|
|
|
public async Task<string> GetAggregatedValueAsync(
|
|
Guid jobGroupId,
|
|
Guid unitId,
|
|
string shortcode,
|
|
Func<Task<string>> computeIfMissing)
|
|
{
|
|
if (string.IsNullOrEmpty(shortcode))
|
|
throw new ArgumentException("Ключ шорткода должен быть указан.", nameof(shortcode));
|
|
|
|
var cacheKey = GetCacheKey(jobGroupId, unitId, shortcode);
|
|
|
|
try
|
|
{
|
|
var cachedValue = await cacheService.GetCachedDataAsync<string>(cacheKey);
|
|
if (cachedValue != null)
|
|
{
|
|
logger.LogDebug(
|
|
"Попадание в кэш для шорткода '{ShortcodeKey}': unit={UnitId} → '{Value}'",
|
|
shortcode, unitId, cachedValue);
|
|
return cachedValue;
|
|
}
|
|
|
|
logger.LogDebug(
|
|
"Промах кэша для шорткода '{ShortcodeKey}': unit={UnitId}. Вычисление...",
|
|
shortcode, unitId);
|
|
|
|
var computedValue = await computeIfMissing();
|
|
|
|
await cacheService.SetCachedDataAsync(cacheKey, computedValue, settings.ValueTtl);
|
|
|
|
logger.LogDebug(
|
|
"Вычислено и сохранено значение для '{ShortcodeKey}': unit={UnitId} → '{Value}' (срок хранения={Ttl})",
|
|
shortcode, unitId, computedValue, settings.ValueTtl);
|
|
|
|
return computedValue;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
logger.LogWarning(
|
|
ex,
|
|
"Ошибка при получении или вычислении значения для шорткода '{ShortcodeKey}' (unit={UnitId}). Возвращена пустая строка.",
|
|
shortcode, unitId);
|
|
|
|
return string.Empty;
|
|
}
|
|
}
|
|
|
|
private static string GetCacheKey(Guid jobGroupId, Guid unitId, string shortcodeKey)
|
|
{
|
|
var safeKey = shortcodeKey
|
|
.Trim()
|
|
.Replace(":", "_")
|
|
.Replace(" ", "_")
|
|
.Replace(".", "_")
|
|
.Replace("%", "")
|
|
.Replace("[", "_")
|
|
.Replace("]", "_")
|
|
.Replace("/", "_")
|
|
.Replace("\\", "_");
|
|
|
|
// ✅ SHA256 от safeKey
|
|
using var sha256 = SHA256.Create();
|
|
var hashBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(safeKey));
|
|
var hashHex = BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
|
|
|
|
// ✅ Новый формат ключа
|
|
return $"gr_shcd_{jobGroupId:N}{unitId:N}_{hashHex}";
|
|
}
|
|
}
|
|
} |