105 lines
5.0 KiB
C#
105 lines
5.0 KiB
C#
using Microsoft.Extensions.Logging;
|
||
using PARR.Core.Common.Interfaces;
|
||
using PARR.Core.Services.HelpDocument.Interfaces;
|
||
using PARR.Domain.Cache;
|
||
using PARR.Domain.DTOs.HelpDocument;
|
||
using PARR.Domain.Settings;
|
||
|
||
namespace PARR.Core.Services.HelpDocument.Implementations
|
||
{
|
||
internal class HelpDocumentService : IHelpDocumentService
|
||
{
|
||
private readonly IHelpDocumentProvider _helpProvider;
|
||
private readonly IRedisCacheService _redisCacheService;
|
||
private readonly HelpDocumentSettings _helpDocumentSettings;
|
||
private readonly ILogger<HelpDocumentService> _logger;
|
||
|
||
public HelpDocumentService(
|
||
IHelpDocumentProvider helpProvider,
|
||
IRedisCacheService redisCacheService,
|
||
HelpDocumentSettings helpDocumentSettings,
|
||
ILogger<HelpDocumentService> logger
|
||
)
|
||
{
|
||
_helpProvider = helpProvider;
|
||
_redisCacheService = redisCacheService;
|
||
_helpDocumentSettings = helpDocumentSettings;
|
||
_logger = logger;
|
||
}
|
||
|
||
|
||
public async Task<HelpDocumentResult?> GetHelpDocumentAsync(string helpId)
|
||
{
|
||
if (string.IsNullOrEmpty(helpId))
|
||
{
|
||
_logger.LogWarning("Значение helpId: '{helpId}' пустое.", helpId);
|
||
return null;
|
||
}
|
||
|
||
var cacheKey = _redisCacheService.GetKey(CacheKeys.HelpDocument.HelpDocumentItem(helpId));
|
||
|
||
_logger.LogDebug("Запрос справки. Проверка наличия в Redis по ключу: {CacheKey}", cacheKey);
|
||
|
||
// 1. Попытка получить данные из Redis
|
||
var cachedData = await _redisCacheService.GetCachedDataAsync<HelpDocumentResult?>(cacheKey, useCompression: true);
|
||
|
||
if (cachedData != null)
|
||
{
|
||
_logger.LogInformation("Документ справки успешно извлечен из кэша Redis. HelpId: {HelpId}", helpId);
|
||
return cachedData;
|
||
}
|
||
|
||
_logger.LogDebug("Кэш пуст или недоступен. Запрос документа напрямую через провайдер для HelpId: {HelpId}", helpId);
|
||
|
||
// 2. Если в Redis пусто, идем в GitLab через наш провайдер
|
||
var remoteDocument = await _helpProvider.GetDocumentAsync(helpId);
|
||
|
||
if (remoteDocument == null)
|
||
{
|
||
_logger.LogWarning("Документ не найден ни в Redis, ни в GitLab. HelpId: {HelpId}", helpId);
|
||
|
||
|
||
// Создаем понятный для пользователя текст-заглушку если нет документации
|
||
remoteDocument = new HelpDocumentResult
|
||
{
|
||
HelpId = helpId,
|
||
Title = "Раздел в разработке",
|
||
Content = "### 📚 Отсутствует документация по данному разделу.\n\n" +
|
||
"Если у вас возникли срочные вопросы, свяжитесь с теми, кто знает на них ответы :)."
|
||
};
|
||
|
||
// Кэшируем заглушку на короткий срок (например, на 5-10 минут), а не на 24 часа.
|
||
// Это нужно, чтобы как только аналитик создаст файл и прилетит хук, кэш обновился,
|
||
// но при этом частые клики пользователей по сломанному вопросику не спамили GitLab запросами 404.
|
||
await _redisCacheService.SetCachedDataAsync(cacheKey, remoteDocument, _helpDocumentSettings.ShortTTL, useCompression: true);
|
||
|
||
return remoteDocument;
|
||
}
|
||
|
||
// 3. Сохраняем полученный документ в Redis для последующих запросов
|
||
await _redisCacheService.SetCachedDataAsync(cacheKey, remoteDocument, _helpDocumentSettings.CacheTTL, useCompression: true);
|
||
|
||
_logger.LogDebug("Вернул документацию из провайдера для HelpId: {HelpId}", helpId);
|
||
|
||
return remoteDocument;
|
||
}
|
||
|
||
|
||
public async Task ClearCacheAsync(string helpId)
|
||
{
|
||
if (string.IsNullOrEmpty(helpId))
|
||
{
|
||
_logger.LogWarning("Попытка очистки кэша: передан пустой helpId.");
|
||
return;
|
||
}
|
||
|
||
var cacheKey = _redisCacheService.GetKey(CacheKeys.HelpDocument.HelpDocumentItem(helpId));
|
||
|
||
_logger.LogInformation("Удаление документа справки из кэша Redis по вебхуку. Ключ: {CacheKey}", cacheKey);
|
||
|
||
await _redisCacheService.DeleteCachedDataAsync(cacheKey);
|
||
}
|
||
|
||
}
|
||
}
|