feat(dal): Результат работы ShortcodesService весь записывается в Redis
This commit is contained in:
@@ -1,10 +0,0 @@
|
|||||||
namespace PARR.DAL.DomainServices.Shortcodes.Models
|
|
||||||
{
|
|
||||||
internal class CachedGroupedShortCode
|
|
||||||
{
|
|
||||||
public string Value { get; set; } = string.Empty;
|
|
||||||
public DateTimeOffset Timestamp { get; set; }
|
|
||||||
public string? Source { get; set; } = "ShortcodesService";
|
|
||||||
public int Version { get; set; } = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -3,13 +3,13 @@ using Microsoft.Extensions.Logging;
|
|||||||
using PARR.Core.Common.Interfaces;
|
using PARR.Core.Common.Interfaces;
|
||||||
using PARR.DAL.Contracts;
|
using PARR.DAL.Contracts;
|
||||||
using PARR.DAL.DomainModels;
|
using PARR.DAL.DomainModels;
|
||||||
using PARR.DAL.DomainServices.Shortcodes.Models;
|
|
||||||
using PARR.DAL.DomainServices.UnitFilterService;
|
using PARR.DAL.DomainServices.UnitFilterService;
|
||||||
using PARR.DAL.Models;
|
using PARR.DAL.Models;
|
||||||
using PARR.DAL.Models.Job;
|
using PARR.DAL.Models.Job;
|
||||||
using PARR.DAL.Services.Interfaces;
|
using PARR.DAL.Services.Interfaces;
|
||||||
using PARR.DAL.Services.Interfaces.Job;
|
using PARR.DAL.Services.Interfaces.Job;
|
||||||
using PARR.DAL.Services.Interfaces.Unit;
|
using PARR.DAL.Services.Interfaces.Unit;
|
||||||
|
using PARR.Domain.Cache.Models;
|
||||||
using PARR.Domain.Common.Template;
|
using PARR.Domain.Common.Template;
|
||||||
using PARR.Domain.Enums;
|
using PARR.Domain.Enums;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
@@ -130,6 +130,19 @@ namespace PARR.DAL.DomainServices.Shortcodes
|
|||||||
|
|
||||||
var callerName = caller ?? "Unknown";
|
var callerName = caller ?? "Unknown";
|
||||||
|
|
||||||
|
// Ключ: shortcodes_result_{TemplateIdN}_{Hash(str)}
|
||||||
|
var cacheKey = cacheService.GetKey(
|
||||||
|
new[] { "shortcodes", "result", template.Id.ToString("N") },
|
||||||
|
new[] { str }
|
||||||
|
);
|
||||||
|
|
||||||
|
var cachedResult = await cacheService.GetCachedDataAsync<ShortcodesResult>(cacheKey).ConfigureAwait(false);
|
||||||
|
if (cachedResult != null)
|
||||||
|
{
|
||||||
|
logger.LogDebug("[{Caller}] Кэш попал для шаблона {TemplateId}", callerName, template.Id);
|
||||||
|
return cachedResult.Data.Result;
|
||||||
|
}
|
||||||
|
|
||||||
logger.LogDebug("[{Caller}] Начата подстановка шорткодов. Вход: '{Input}', templateId={TemplateId}", callerName, str, template.Id);
|
logger.LogDebug("[{Caller}] Начата подстановка шорткодов. Вход: '{Input}', templateId={TemplateId}", callerName, str, template.Id);
|
||||||
|
|
||||||
var result = str;
|
var result = str;
|
||||||
@@ -140,19 +153,29 @@ namespace PARR.DAL.DomainServices.Shortcodes
|
|||||||
var shortcodes = GetShortCodes(result).Select(m => m.Value).ToList();
|
var shortcodes = GetShortCodes(result).Select(m => m.Value).ToList();
|
||||||
if (!shortcodes.Any()) break;
|
if (!shortcodes.Any()) break;
|
||||||
|
|
||||||
// Подготавливаем данные с догрузкой при необходимости
|
|
||||||
var data = await PrepareTemplateDataAsync(template, shortcodes, callerName).ConfigureAwait(false);
|
var data = await PrepareTemplateDataAsync(template, shortcodes, callerName).ConfigureAwait(false);
|
||||||
|
|
||||||
var oldResult = result;
|
var oldResult = result;
|
||||||
|
|
||||||
// Подстановка всех типов шорткодов
|
|
||||||
result = await ApplyAllShortcodesOnceAsync(result, data, shortcodes, callerName).ConfigureAwait(false);
|
result = await ApplyAllShortcodesOnceAsync(result, data, shortcodes, callerName).ConfigureAwait(false);
|
||||||
|
|
||||||
iteration++;
|
iteration++;
|
||||||
|
|
||||||
if (result == oldResult) break;
|
if (result == oldResult) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Сохранение в кэш (только если были изменения)
|
||||||
|
if (!string.IsNullOrEmpty(result) && result != str)
|
||||||
|
{
|
||||||
|
var toCache = new ShortcodesResult
|
||||||
|
{
|
||||||
|
Data = new ShortcodesResultDto { Result = result },
|
||||||
|
Timestamp = DateTimeOffset.UtcNow,
|
||||||
|
Source = typeof(ShortcodesService).Name
|
||||||
|
};
|
||||||
|
|
||||||
|
await cacheService.SetCachedDataAsync(cacheKey, toCache, TimeSpan.FromMinutes(15)).ConfigureAwait(false);
|
||||||
|
logger.LogDebug("[{Caller}] Результат сохранён в кэш для ключа '{Key}'", callerName, cacheKey);
|
||||||
|
}
|
||||||
|
|
||||||
logger.LogDebug("[{Caller}] Подстановка завершена. Результат: '{Result}'", callerName, result);
|
logger.LogDebug("[{Caller}] Подстановка завершена. Результат: '{Result}'", callerName, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -772,11 +795,11 @@ namespace PARR.DAL.DomainServices.Shortcodes
|
|||||||
//var cacheKey = $"gr_shcd_{jobGroupId:N}_{unitId:N}_{ComputeHash(fullShortcode)}";
|
//var cacheKey = $"gr_shcd_{jobGroupId:N}_{unitId:N}_{ComputeHash(fullShortcode)}";
|
||||||
var cacheKey = cacheService.GetKey(new[] { "grouped", "shortcode", $"{jobGroupId:N}", $"{unitId:N}" }, new[] { fullShortcode });
|
var cacheKey = cacheService.GetKey(new[] { "grouped", "shortcode", $"{jobGroupId:N}", $"{unitId:N}" }, new[] { fullShortcode });
|
||||||
|
|
||||||
var cachedData = await cacheService.GetCachedDataAsync<CachedGroupedShortCode>(cacheKey).ConfigureAwait(false);
|
var cachedData = await cacheService.GetCachedDataAsync<GroupedShortcode>(cacheKey).ConfigureAwait(false);
|
||||||
if (cachedData != null)
|
if (cachedData != null)
|
||||||
{
|
{
|
||||||
logger.LogDebug("[{Caller}] Кэш попал для GroupedShortCode '{Name}': {Value}", caller, fullShortcode, cachedData.Value);
|
logger.LogDebug("[{Caller}] Кэш попал для GroupedShortCode '{Name}': {Value}", caller, fullShortcode, cachedData.Data.Value);
|
||||||
return cachedData.Value;
|
return cachedData.Data.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.LogDebug("[{Caller}] Кэш промахнут для GroupedShortCode '{Name}'. Запрашиваем из БД.", caller, fullShortcode);
|
logger.LogDebug("[{Caller}] Кэш промахнут для GroupedShortCode '{Name}'. Запрашиваем из БД.", caller, fullShortcode);
|
||||||
@@ -793,14 +816,12 @@ namespace PARR.DAL.DomainServices.Shortcodes
|
|||||||
// Не кэшируем пустые значения
|
// Не кэшируем пустые значения
|
||||||
if (!string.IsNullOrEmpty(mostFrequentValue))
|
if (!string.IsNullOrEmpty(mostFrequentValue))
|
||||||
{
|
{
|
||||||
var toCache = new CachedGroupedShortCode
|
var toCache = new GroupedShortcode
|
||||||
{
|
{
|
||||||
Value = mostFrequentValue,
|
Data = new GroupedShortcodeDto { Value = mostFrequentValue },
|
||||||
Timestamp = DateTimeOffset.UtcNow,
|
Timestamp = DateTimeOffset.UtcNow,
|
||||||
Source = typeof(ShortcodesService).Name,
|
Source = typeof(ShortcodesService).Name
|
||||||
Version = 1
|
|
||||||
};
|
};
|
||||||
|
|
||||||
await cacheService.SetCachedDataAsync(cacheKey, toCache, TimeSpan.FromHours(1)).ConfigureAwait(false);
|
await cacheService.SetCachedDataAsync(cacheKey, toCache, TimeSpan.FromHours(1)).ConfigureAwait(false);
|
||||||
return mostFrequentValue;
|
return mostFrequentValue;
|
||||||
}
|
}
|
||||||
|
|||||||
21
PARR.Domain/Cache/Models/GroupedShortсode.cs
Normal file
21
PARR.Domain/Cache/Models/GroupedShortсode.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
using PARR.Domain.Cache.Models.Base;
|
||||||
|
|
||||||
|
namespace PARR.Domain.Cache.Models
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Модель кэша для шорткодов группированных работ
|
||||||
|
/// </summary>
|
||||||
|
public class GroupedShortcode : IBaseCache<GroupedShortcodeDto>
|
||||||
|
{
|
||||||
|
public required GroupedShortcodeDto Data { get; set; }
|
||||||
|
|
||||||
|
public DateTimeOffset Timestamp { get; set; }
|
||||||
|
|
||||||
|
public required string Source { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GroupedShortcodeDto
|
||||||
|
{
|
||||||
|
public required string Value { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
21
PARR.Domain/Cache/Models/ShortcodesResult.cs
Normal file
21
PARR.Domain/Cache/Models/ShortcodesResult.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
using PARR.Domain.Cache.Models.Base;
|
||||||
|
|
||||||
|
namespace PARR.Domain.Cache.Models
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Модель кэша для результата подстановки всех шорткодов в строке
|
||||||
|
/// </summary>
|
||||||
|
public class ShortcodesResult : IBaseCache<ShortcodesResultDto>
|
||||||
|
{
|
||||||
|
public required ShortcodesResultDto Data { get; set; }
|
||||||
|
|
||||||
|
public DateTimeOffset Timestamp { get; set; }
|
||||||
|
|
||||||
|
public required string Source { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ShortcodesResultDto
|
||||||
|
{
|
||||||
|
public required string Result { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -476,7 +476,7 @@ internal class SimpleTemplateSynchronizer : ITemplateSynchronizer
|
|||||||
// Находим все шаблоны со статусом Unused
|
// Находим все шаблоны со статусом Unused
|
||||||
var unusedTemplates = await templateService.Get()
|
var unusedTemplates = await templateService.Get()
|
||||||
.Include(t => t.Unit)
|
.Include(t => t.Unit)
|
||||||
.Where(t => t.StatusTypeId == TemplateStatusTypeEnum.Unused || t.StatusTypeId == TemplateStatusTypeEnum.Error)
|
.Where(t => t.StatusTypeId == TemplateStatusTypeEnum.Unused)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
if (!unusedTemplates.Any())
|
if (!unusedTemplates.Any())
|
||||||
|
|||||||
Reference in New Issue
Block a user