Files
parr_api/PARR.Core/Services/HelpDocument/Implementations/HelpDocumentService.cs

105 lines
5.0 KiB
C#
Raw Normal View History

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);
}
}
}