This commit is contained in:
kislovdm
2026-03-10 17:02:08 +03:00
parent 0fb652664f
commit e4ac2e04f7
5 changed files with 84 additions and 24 deletions
+20 -1
View File
@@ -33,19 +33,24 @@ public class DealService
{ {
var deals = await _pepperClient.GetLatestDealsAsync(cancellationToken); var deals = await _pepperClient.GetLatestDealsAsync(cancellationToken);
_logger.LogInformation("Начата обработка полученных скидок: всего {DealCount}", deals.Count);
// Хелсчек: успешный запрос, вернувший более одной скидки (пусть и не новой) // Хелсчек: успешный запрос, вернувший более одной скидки (пусть и не новой)
if (deals.Count > 1) if (deals.Count > 1)
{ {
_healthMonitor.ReportSuccess(DateTimeOffset.UtcNow); _healthMonitor.ReportSuccess(DateTimeOffset.UtcNow);
_logger.LogDebug("HealthCheck: успешно получено более одной скидки ({DealCount})", deals.Count);
} }
// Загружаем активные подписки один раз на проход // Загружаем активные подписки один раз на проход
var subscriptions = await _subscriptionRepository.GetAllActiveAsync(cancellationToken); var subscriptions = await _subscriptionRepository.GetAllActiveAsync(cancellationToken);
_logger.LogInformation("Загружено активных подписок: {SubscriptionCount}", subscriptions.Count);
foreach (var deal in deals) foreach (var deal in deals)
{ {
if (await _repository.ExistsAsync(deal.Id, cancellationToken)) if (await _repository.ExistsAsync(deal.Id, cancellationToken))
{ {
_logger.LogDebug("Скидка уже есть в репозитории и будет пропущена: {DealId}", deal.Id);
continue; continue;
} }
@@ -58,6 +63,7 @@ public class DealService
if (subscriptions.Count == 0) if (subscriptions.Count == 0)
{ {
_logger.LogDebug("Активные подписки отсутствуют. Фильтрация по ключевым словам пропущена для скидки {DealId}", deal.Id);
continue; continue;
} }
@@ -67,16 +73,29 @@ public class DealService
{ {
if (!subscription.IsActive) if (!subscription.IsActive)
{ {
_logger.LogDebug("Подписка {SubscriptionId} неактивна и будет пропущена", subscription.Id);
continue; continue;
} }
var keywords = ParseKeywords(subscription.Keywords); var keywords = ParseKeywords(subscription.Keywords);
if (keywords.Count == 0) if (keywords.Count == 0)
{ {
_logger.LogDebug("У подписки {SubscriptionId} не удалось извлечь ключевые слова из строки: \"{RawKeywords}\"",
subscription.Id,
subscription.Keywords);
continue; continue;
} }
if (IsMatch(searchableText, keywords)) var isMatch = IsMatch(searchableText, keywords);
_logger.LogDebug(
"Результат фильтрации скидки {DealId} по подписке {SubscriptionId}: {IsMatch}. Текст: \"{Text}\"; ключевые слова: {Keywords}",
deal.Id,
subscription.Id,
isMatch,
searchableText,
string.Join(", ", keywords));
if (isMatch)
{ {
await _notifier.NotifyDealToChatAsync(deal, subscription.ChatId, cancellationToken); await _notifier.NotifyDealToChatAsync(deal, subscription.ChatId, cancellationToken);
} }
@@ -45,7 +45,10 @@ public class PepperClient : IPepperClient
public async Task<IReadOnlyList<Deal>> GetLatestDealsAsync(CancellationToken cancellationToken) public async Task<IReadOnlyList<Deal>> GetLatestDealsAsync(CancellationToken cancellationToken)
{ {
using var request = new HttpRequestMessage(HttpMethod.Get, Url); using var request = new HttpRequestMessage(HttpMethod.Get, Url);
_logger.LogDebug("Отправка запроса за последними скидками Pepper: {Url}", Url);
using var response = await _httpClient.SendAsync(request, cancellationToken); using var response = await _httpClient.SendAsync(request, cancellationToken);
_logger.LogDebug("Получен ответ от Pepper: {StatusCode}", (int)response.StatusCode);
response.EnsureSuccessStatusCode(); response.EnsureSuccessStatusCode();
@@ -58,7 +61,12 @@ public class PepperClient : IPepperClient
return Array.Empty<Deal>(); return Array.Empty<Deal>();
} }
return dto.Deals.Select(MapToDeal).ToArray(); _logger.LogInformation("Успешно распарсен ответ Pepper: всего сделок в ответе {DealCount}", dto.Deals.Count);
var mappedDeals = dto.Deals.Select(MapToDeal).ToArray();
_logger.LogDebug("После маппинга в доменную модель осталось сделок: {MappedCount}", mappedDeals.Length);
return mappedDeals;
} }
private static Deal MapToDeal(PepperDeal dto) private static Deal MapToDeal(PepperDeal dto)
+1 -1
View File
@@ -14,7 +14,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Data.Sqlite" Version="10.0.3" /> <PackageReference Include="Microsoft.Data.Sqlite" Version="10.0.3" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.3" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.3" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="10.0.3" /> <PackageReference Include="NLog.Web.AspNetCore" Version="6.1.2" />
<PackageReference Include="Telegram.Bot" Version="22.9.5.3" /> <PackageReference Include="Telegram.Bot" Version="22.9.5.3" />
</ItemGroup> </ItemGroup>
+24 -11
View File
@@ -10,14 +10,16 @@ using PepperBot.Infrastructure.Health;
using PepperBot.Infrastructure.Pepper; using PepperBot.Infrastructure.Pepper;
using PepperBot.Infrastructure.Telegram; using PepperBot.Infrastructure.Telegram;
using Telegram.Bot; using Telegram.Bot;
using NLog.Web;
var builder = WebApplication.CreateBuilder(args); var logger = NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
builder.Services.AddLogging(logging => try
{ {
logging.ClearProviders(); var builder = WebApplication.CreateBuilder(args);
logging.AddConsole();
}); builder.Logging.ClearProviders();
builder.Host.UseNLog();
builder.Services.AddSingleton<IDealRepository, SqliteDealRepository>(); builder.Services.AddSingleton<IDealRepository, SqliteDealRepository>();
builder.Services.AddSingleton<ISubscriptionRepository, SqliteSubscriptionRepository>(); builder.Services.AddSingleton<ISubscriptionRepository, SqliteSubscriptionRepository>();
@@ -33,12 +35,12 @@ builder.Services.AddSingleton<ITelegramBotClient>(_ =>
return new TelegramBotClient(token); return new TelegramBotClient(token);
}); });
builder.Services.AddHostedService<BotWorker>(); builder.Services.AddHostedService<BotWorker>();
var app = builder.Build(); var app = builder.Build();
app.MapGet("/health", (IHealthMonitor healthMonitor) => app.MapGet("/health", (IHealthMonitor healthMonitor) =>
{ {
var successTtl = TimeSpan.FromMinutes(15); var successTtl = TimeSpan.FromMinutes(15);
var isHealthy = healthMonitor.IsHealthy(successTtl); var isHealthy = healthMonitor.IsHealthy(successTtl);
@@ -52,6 +54,17 @@ app.MapGet("/health", (IHealthMonitor healthMonitor) =>
} }
return Results.StatusCode(StatusCodes.Status503ServiceUnavailable); return Results.StatusCode(StatusCodes.Status503ServiceUnavailable);
}); });
await app.RunAsync(); logger.LogInformation("Запуск PepperBot приложения");
await app.RunAsync();
}
catch (Exception ex)
{
logger.LogError(ex, "Приложение остановлено из-за необработанного исключения");
throw;
}
finally
{
global::NLog.LogManager.Shutdown();
}
+20
View File
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true"
throwConfigExceptions="true">
<targets>
<target xsi:type="Console" name="console" layout="${longdate}|${level:uppercase=true}|${logger}|${message} ${exception:format=ToString}" />
</targets>
<rules>
<!-- Более подробные логи для парсинга и фильтров -->
<logger name="PepperBot.Infrastructure.Pepper.PepperClient" minlevel="Debug" writeTo="console" />
<logger name="PepperBot.Application.Services.DealService" minlevel="Debug" writeTo="console" />
<!-- Общий уровень для остальных логгеров -->
<logger name="*" minlevel="Info" writeTo="console" />
</rules>
</nlog>