fix services

This commit is contained in:
Leonid Pershin
2025-10-17 02:59:56 +03:00
parent d64c4742cf
commit 392e6bc7f5
3 changed files with 44 additions and 80 deletions

View File

@@ -146,20 +146,12 @@ try
builder.Services.AddScoped<ITelegramCommandProcessor, TelegramCommandProcessor>(); builder.Services.AddScoped<ITelegramCommandProcessor, TelegramCommandProcessor>();
builder.Services.AddScoped<ITelegramMessageHandler, TelegramMessageHandler>(); builder.Services.AddScoped<ITelegramMessageHandler, TelegramMessageHandler>();
// Регистрируем TelegramBotService как scoped и используем один экземпляр для интерфейса и HostedService // Регистрируем TelegramBotService как singleton и hosted service
builder.Services.AddScoped<TelegramBotService>(); builder.Services.AddSingleton<ITelegramBotService, TelegramBotService>();
builder.Services.AddScoped<ITelegramBotService>(sp => builder.Services.AddSingleton<IHostedService>(provider =>
sp.GetRequiredService<TelegramBotService>() (IHostedService)provider.GetRequiredService<ITelegramBotService>()
); );
// Создаем обертку для HostedService, которая создает scope
builder.Services.AddSingleton<IHostedService>(sp =>
{
var serviceProvider = sp.GetRequiredService<IServiceProvider>();
var logger = sp.GetRequiredService<ILogger<TelegramBotHostedService>>();
return new TelegramBotHostedService(serviceProvider, logger);
});
// Регистрируем Health Checks // Регистрируем Health Checks
builder builder
.Services.AddHealthChecks() .Services.AddHealthChecks()

View File

@@ -1,6 +1,6 @@
using ChatBot.Models.Configuration;
using ChatBot.Services.Telegram.Interfaces; using ChatBot.Services.Telegram.Interfaces;
using Microsoft.Extensions.Options; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Telegram.Bot; using Telegram.Bot;
using Telegram.Bot.Polling; using Telegram.Bot.Polling;
using Telegram.Bot.Types; using Telegram.Bot.Types;
@@ -11,41 +11,41 @@ namespace ChatBot.Services.Telegram.Services
/// <summary> /// <summary>
/// Основной сервис Telegram бота /// Основной сервис Telegram бота
/// </summary> /// </summary>
public class TelegramBotService : BackgroundService, ITelegramBotService public class TelegramBotService : ITelegramBotService, IHostedService
{ {
private readonly ILogger<TelegramBotService> _logger; private readonly ILogger<TelegramBotService> _logger;
private readonly ITelegramBotClient _botClient; private readonly ITelegramBotClient _botClient;
private readonly ITelegramMessageHandler _messageHandler; private readonly IServiceProvider _serviceProvider;
private readonly ITelegramErrorHandler _errorHandler; private CancellationTokenSource? _cancellationTokenSource;
public TelegramBotService( public TelegramBotService(
ILogger<TelegramBotService> logger, ILogger<TelegramBotService> logger,
ITelegramBotClient botClient, ITelegramBotClient botClient,
ITelegramMessageHandler messageHandler, IServiceProvider serviceProvider
ITelegramErrorHandler errorHandler
) )
{ {
_logger = logger; _logger = logger;
_botClient = botClient; _botClient = botClient;
_messageHandler = messageHandler; _serviceProvider = serviceProvider;
_errorHandler = errorHandler;
} }
/// <summary> /// <summary>
/// Запускает бота /// Запускает бота
/// </summary> /// </summary>
public override async Task StartAsync(CancellationToken cancellationToken) public async Task StartAsync(CancellationToken cancellationToken = default)
{ {
var receiverOptions = new ReceiverOptions var receiverOptions = new ReceiverOptions
{ {
AllowedUpdates = new[] { UpdateType.Message }, AllowedUpdates = new[] { UpdateType.Message },
}; };
_cancellationTokenSource = new CancellationTokenSource();
_botClient.StartReceiving( _botClient.StartReceiving(
updateHandler: _messageHandler.HandleUpdateAsync, updateHandler: HandleUpdateAsync,
errorHandler: _errorHandler.HandlePollingErrorAsync, errorHandler: HandlePollingErrorAsync,
receiverOptions: receiverOptions, receiverOptions: receiverOptions,
cancellationToken: cancellationToken cancellationToken: _cancellationTokenSource.Token
); );
var botInfo = await GetBotInfoAsync(cancellationToken); var botInfo = await GetBotInfoAsync(cancellationToken);
@@ -62,10 +62,12 @@ namespace ChatBot.Services.Telegram.Services
/// <summary> /// <summary>
/// Останавливает бота /// Останавливает бота
/// </summary> /// </summary>
public override async Task StopAsync(CancellationToken cancellationToken) public Task StopAsync(CancellationToken cancellationToken = default)
{ {
_logger.LogInformation("Stopping Telegram bot service..."); _logger.LogInformation("Stopping Telegram bot service...");
await base.StopAsync(cancellationToken); _cancellationTokenSource?.Cancel();
_cancellationTokenSource?.Dispose();
return Task.CompletedTask;
} }
/// <summary> /// <summary>
@@ -84,15 +86,31 @@ namespace ChatBot.Services.Telegram.Services
} }
} }
protected override async Task ExecuteAsync(CancellationToken stoppingToken) private async Task HandleUpdateAsync(
ITelegramBotClient botClient,
Update update,
CancellationToken cancellationToken
)
{ {
await StartAsync(stoppingToken); // Create a new scope for each message processing
using var scope = _serviceProvider.CreateScope();
var messageHandler =
scope.ServiceProvider.GetRequiredService<ITelegramMessageHandler>();
// Keep the service running await messageHandler.HandleUpdateAsync(botClient, update, cancellationToken);
while (!stoppingToken.IsCancellationRequested)
{
await Task.Delay(1000, stoppingToken);
} }
private async Task HandlePollingErrorAsync(
ITelegramBotClient botClient,
Exception exception,
CancellationToken cancellationToken
)
{
// Create a new scope for error handling
using var scope = _serviceProvider.CreateScope();
var errorHandler = scope.ServiceProvider.GetRequiredService<ITelegramErrorHandler>();
await errorHandler.HandlePollingErrorAsync(botClient, exception, cancellationToken);
} }
} }
} }

View File

@@ -1,46 +0,0 @@
using ChatBot.Services.Telegram.Interfaces;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace ChatBot.Services
{
/// <summary>
/// Hosted service wrapper for TelegramBotService to handle scoped dependencies
/// </summary>
public class TelegramBotHostedService : IHostedService
{
private readonly IServiceProvider _serviceProvider;
private readonly ILogger<TelegramBotHostedService> _logger;
private ITelegramBotService? _botService;
public TelegramBotHostedService(
IServiceProvider serviceProvider,
ILogger<TelegramBotHostedService> logger
)
{
_serviceProvider = serviceProvider;
_logger = logger;
}
public async Task StartAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Starting Telegram Bot Hosted Service...");
using var scope = _serviceProvider.CreateScope();
_botService = scope.ServiceProvider.GetRequiredService<ITelegramBotService>();
await _botService.StartAsync(cancellationToken);
}
public async Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Stopping Telegram Bot Hosted Service...");
if (_botService != null)
{
await _botService.StopAsync(cancellationToken);
}
}
}
}