гзв
This commit is contained in:
@@ -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)
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|
||||||
|
|||||||
+34
-21
@@ -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,25 +35,36 @@ 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 isHealthy = healthMonitor.IsHealthy(successTtl);
|
|
||||||
|
|
||||||
if (isHealthy)
|
|
||||||
{
|
{
|
||||||
return Results.Ok(new
|
var successTtl = TimeSpan.FromMinutes(15);
|
||||||
|
var isHealthy = healthMonitor.IsHealthy(successTtl);
|
||||||
|
|
||||||
|
if (isHealthy)
|
||||||
{
|
{
|
||||||
status = "Healthy",
|
return Results.Ok(new
|
||||||
lastSuccessfulRequestAt = healthMonitor.LastSuccessfulRequestAt
|
{
|
||||||
});
|
status = "Healthy",
|
||||||
}
|
lastSuccessfulRequestAt = healthMonitor.LastSuccessfulRequestAt
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
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();
|
||||||
|
}
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|
||||||
Reference in New Issue
Block a user