руфдер
This commit is contained in:
@@ -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,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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user