руфдер

This commit is contained in:
kislovdm
2026-03-10 15:52:32 +03:00
parent 808eebb7c7
commit d7443883cd
6 changed files with 95 additions and 8 deletions
@@ -0,0 +1,21 @@
namespace PepperBot.Application.Interfaces;
public interface IHealthMonitor
{
/// <summary>
/// Отметить успешный запрос к Pepper, вернувший более одной скидки.
/// </summary>
/// <param name="timestamp">Время успешного запроса (UTC).</param>
void ReportSuccess(DateTimeOffset timestamp);
/// <summary>
/// Время последнего успешного запроса или null, если их ещё не было.
/// </summary>
DateTimeOffset? LastSuccessfulRequestAt { get; }
/// <summary>
/// Текущее состояние healthcheck.
/// </summary>
bool IsHealthy(TimeSpan successTtl);
}
+10 -1
View File
@@ -10,23 +10,32 @@ public class DealService
private readonly IDealRepository _repository;
private readonly ITelegramNotifier _notifier;
private readonly ILogger<DealService> _logger;
private readonly IHealthMonitor _healthMonitor;
public DealService(
IPepperClient pepperClient,
IDealRepository repository,
ITelegramNotifier notifier,
ILogger<DealService> logger)
ILogger<DealService> logger,
IHealthMonitor healthMonitor)
{
_pepperClient = pepperClient;
_repository = repository;
_notifier = notifier;
_logger = logger;
_healthMonitor = healthMonitor;
}
public async Task CheckAndNotifyAsync(CancellationToken cancellationToken)
{
var deals = await _pepperClient.GetLatestDealsAsync(cancellationToken);
// Хелсчек: успешный запрос, вернувший более одной скидки (пусть и не новой)
if (deals.Count > 1)
{
_healthMonitor.ReportSuccess(DateTimeOffset.UtcNow);
}
foreach (var deal in deals)
{
if (await _repository.ExistsAsync(deal.Id, cancellationToken))
@@ -0,0 +1,30 @@
using System.Threading;
using PepperBot.Application.Interfaces;
namespace PepperBot.Infrastructure.Health;
public class PepperHealthMonitor : IHealthMonitor
{
private DateTimeOffset? _lastSuccessfulRequestAt;
public DateTimeOffset? LastSuccessfulRequestAt => _lastSuccessfulRequestAt;
public void ReportSuccess(DateTimeOffset timestamp)
{
// Просто запоминаем последнее успешное время; избыточную синхронизацию не вводим
// так как запись идёт по одному воркеру.
_lastSuccessfulRequestAt = timestamp;
}
public bool IsHealthy(TimeSpan successTtl)
{
var last = _lastSuccessfulRequestAt;
if (last is null)
{
return false;
}
return DateTimeOffset.UtcNow - last.Value < successTtl;
}
}
+5 -1
View File
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
@@ -7,6 +7,10 @@
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Data.Sqlite" Version="10.0.3" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.3" />
+26 -6
View File
@@ -1,14 +1,16 @@
using PepperBot;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using PepperBot.Application.Services;
using PepperBot;
using PepperBot.Application.Interfaces;
using PepperBot.Application.Services;
using PepperBot.Infrastructure.Data;
using PepperBot.Infrastructure.Health;
using PepperBot.Infrastructure.Pepper;
using PepperBot.Infrastructure.Telegram;
var builder = Host.CreateApplicationBuilder(args);
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddLogging(logging =>
{
@@ -19,10 +21,28 @@ builder.Services.AddLogging(logging =>
builder.Services.AddSingleton<IDealRepository, SqliteDealRepository>();
builder.Services.AddSingleton<IPepperClient, PepperClient>();
builder.Services.AddSingleton<ITelegramNotifier, TelegramNotifier>();
builder.Services.AddSingleton<IHealthMonitor, PepperHealthMonitor>();
builder.Services.AddSingleton<DealService>();
builder.Services.AddHostedService<BotWorker>();
var host = builder.Build();
var app = builder.Build();
await host.RunAsync();
app.MapGet("/health", (IHealthMonitor healthMonitor) =>
{
var successTtl = TimeSpan.FromMinutes(15);
var isHealthy = healthMonitor.IsHealthy(successTtl);
if (isHealthy)
{
return Results.Ok(new
{
status = "Healthy",
lastSuccessfulRequestAt = healthMonitor.LastSuccessfulRequestAt
});
}
return Results.StatusCode(StatusCodes.Status503ServiceUnavailable);
});
await app.RunAsync();
+3
View File
@@ -8,7 +8,10 @@ services:
environment:
- TELEGRAM_BOT_TOKEN=${TELEGRAM_BOT_TOKEN}
- TELEGRAM_CHAT_ID=${TELEGRAM_CHAT_ID}
- ASPNETCORE_URLS=http://0.0.0.0:8080
volumes:
- ./data:/app/data
ports:
- "9001:8080"
restart: unless-stopped