diff --git a/PARR.API/Controllers/V1/HelpDocumentController.cs b/PARR.API/Controllers/V1/HelpDocumentController.cs index 86e3b7fa..b1aad9b4 100644 --- a/PARR.API/Controllers/V1/HelpDocumentController.cs +++ b/PARR.API/Controllers/V1/HelpDocumentController.cs @@ -7,6 +7,7 @@ using PARR.API.Contracts.V1.Responses.Base; using PARR.API.Controllers.V1.Base; using PARR.Core.Services.HelpDocument.Interfaces; using PARR.Domain.Common.Roles; +using PARR.Domain.Exceptions; using PARR.Domain.Settings; using System.Text.Json.Nodes; @@ -75,13 +76,13 @@ namespace PARR.API.Controllers.V1 if (!Request.Headers.TryGetValue("X-Gitlab-Token", out var receivedToken)) { _logger.LogWarning("Запрос вебхука отклонен. Отсутствует заголовок X-Gitlab-Token."); - return Unauthorized("Отсутствует авторизационный токен вебхука."); + throw new UnauthorizedException("Отсутствует авторизационный токен вебхука."); } if (receivedToken.ToString() != _helpDocumentSettings.WebhookToken) { _logger.LogWarning("Запрос вебхука отклонен. Передан невалидный Secret Token."); - return Unauthorized("Неверный токен вебхука."); + throw new UnauthorizedException("Неверный токен вебхука."); } #endregion @@ -164,7 +165,7 @@ namespace PARR.API.Controllers.V1 _logger.LogError(ex, "Ошибка при обработке Webhook от GitLab"); // Возвращаем 200 или 500 в зависимости от политики. // Обычно возвращают BadRequest/InternalServerError, чтобы в GitLab в истории вебхуков была видна ошибка отладки. - return StatusCode(500, "Внутренняя ошибка обработки вебхука"); + throw new ExternalServiceException("Внутренняя ошибка обработки вебхука"); } } diff --git a/PARR.API/appsettings.json b/PARR.API/appsettings.json index b729c994..6062378b 100644 --- a/PARR.API/appsettings.json +++ b/PARR.API/appsettings.json @@ -127,6 +127,7 @@ "DefaultBranch": "main" }, "CacheTTL": "23:59:00", + "ShortTTL": "00:10:00", "WebhookToken": "ParrSecret2026" } } diff --git a/PARR.Core/Services/HelpDocument/Implementations/HelpDocumentService.cs b/PARR.Core/Services/HelpDocument/Implementations/HelpDocumentService.cs index 58610a6f..ae6a868c 100644 --- a/PARR.Core/Services/HelpDocument/Implementations/HelpDocumentService.cs +++ b/PARR.Core/Services/HelpDocument/Implementations/HelpDocumentService.cs @@ -57,7 +57,23 @@ namespace PARR.Core.Services.HelpDocument.Implementations if (remoteDocument == null) { _logger.LogWarning("Документ не найден ни в Redis, ни в GitLab. HelpId: {HelpId}", helpId); - return null; + + + // Создаем понятный для пользователя текст-заглушку если нет документации + 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 для последующих запросов diff --git a/PARR.Domain/Settings/HelpDocumentSettings.cs b/PARR.Domain/Settings/HelpDocumentSettings.cs index 429e8659..76b093a2 100644 --- a/PARR.Domain/Settings/HelpDocumentSettings.cs +++ b/PARR.Domain/Settings/HelpDocumentSettings.cs @@ -12,6 +12,11 @@ /// public TimeSpan CacheTTL { get; init; } = TimeSpan.FromHours(1); + /// + /// Коротки TTL для страниц где не найдена документация. По умолчанию 10 минут. + /// + public TimeSpan ShortTTL { get; init; } = TimeSpan.FromMinutes(10); + public string WebhookToken { get; set; } = string.Empty; }