From c8da9e618bce9943be77d4b9066efc8133aea620 Mon Sep 17 00:00:00 2001 From: Sergey Nazarov Date: Thu, 28 Mar 2024 09:51:19 +0000 Subject: [PATCH] Add message dispatcher (#3) Reviewed-on: https://gitea.musk.fun/nocr/telegram-client/pulls/3 Co-authored-by: Sergey Nazarov Co-committed-by: Sergey Nazarov --- Directory.Packages.props | 7 +-- .../{ => Bots}/BotClient.cs | 5 ++- .../IMessageDispatcherHandler.cs | 7 +++ .../IMessageDispatcherQueue.cs | 10 +++++ .../MessageDispatcherBackgroundService.cs | 12 +++++ .../MessageDispatcherHandler.cs | 36 +++++++++++++++ .../MessageDispatcherOptions.cs | 7 +++ .../MessageDispatcherQueue.cs | 19 ++++++++ .../StartMessage/StartMessageHandler.cs | 12 ++--- .../StartMessage/StartMessageMatcher.cs | 2 +- .../SubscribeMessageHandler.cs | 26 +++++------ .../SubscribeMessageMatcher.cs | 11 +++++ .../SubscriptionsMessageHandler.cs | 45 +++++++++++++++++++ .../SubscriptionsMessageMatcher.cs | 11 +++++ .../{ => Handlers}/TextMatchMatchedHandler.cs | 22 ++------- .../Matches/TextMatchExtensions.cs | 32 +++++++++++++ .../Nocr.TelegramClient.AppServices.csproj | 20 ++++----- .../ServiceCollectionExtensions.cs | 8 ++++ .../IRepeatableBackgroundServiceHandler.cs | 6 +++ .../RepeatableBackgroundService.cs | 42 +++++++++++++++++ .../RepeatableServiceOptions.cs | 8 ++++ .../Nocr.TelegramClient.Core.csproj | 6 ++- .../Infrastructure/Startup.cs | 1 + src/Nocr.TelegramClient.Host/appsettings.json | 4 ++ 24 files changed, 302 insertions(+), 57 deletions(-) rename src/Nocr.TelegramClient.AppServices/{ => Bots}/BotClient.cs (87%) create mode 100644 src/Nocr.TelegramClient.AppServices/Bots/MessageDispatcher/IMessageDispatcherHandler.cs create mode 100644 src/Nocr.TelegramClient.AppServices/Bots/MessageDispatcher/IMessageDispatcherQueue.cs create mode 100644 src/Nocr.TelegramClient.AppServices/Bots/MessageDispatcher/MessageDispatcherBackgroundService.cs create mode 100644 src/Nocr.TelegramClient.AppServices/Bots/MessageDispatcher/MessageDispatcherHandler.cs create mode 100644 src/Nocr.TelegramClient.AppServices/Bots/MessageDispatcher/MessageDispatcherOptions.cs create mode 100644 src/Nocr.TelegramClient.AppServices/Bots/MessageDispatcher/MessageDispatcherQueue.cs create mode 100644 src/Nocr.TelegramClient.AppServices/Handlers/Messages/SubscribeMessage/SubscribeMessageMatcher.cs create mode 100644 src/Nocr.TelegramClient.AppServices/Handlers/Messages/SubscriptionsMessage/SubscriptionsMessageHandler.cs create mode 100644 src/Nocr.TelegramClient.AppServices/Handlers/Messages/SubscriptionsMessage/SubscriptionsMessageMatcher.cs rename src/Nocr.TelegramClient.AppServices/Matches/{ => Handlers}/TextMatchMatchedHandler.cs (67%) create mode 100644 src/Nocr.TelegramClient.AppServices/Matches/TextMatchExtensions.cs create mode 100644 src/Nocr.TelegramClient.Core/BackgroundJobs/IRepeatableBackgroundServiceHandler.cs create mode 100644 src/Nocr.TelegramClient.Core/BackgroundJobs/RepeatableBackgroundService.cs create mode 100644 src/Nocr.TelegramClient.Core/BackgroundJobs/RepeatableServiceOptions.cs diff --git a/Directory.Packages.props b/Directory.Packages.props index 467cb4b..bf70a22 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -7,9 +7,9 @@ 0.16.0 - - - + + + @@ -30,5 +30,6 @@ + \ No newline at end of file diff --git a/src/Nocr.TelegramClient.AppServices/BotClient.cs b/src/Nocr.TelegramClient.AppServices/Bots/BotClient.cs similarity index 87% rename from src/Nocr.TelegramClient.AppServices/BotClient.cs rename to src/Nocr.TelegramClient.AppServices/Bots/BotClient.cs index 224b900..904baf4 100644 --- a/src/Nocr.TelegramClient.AppServices/BotClient.cs +++ b/src/Nocr.TelegramClient.AppServices/Bots/BotClient.cs @@ -1,10 +1,11 @@ using Insight.TelegramBot; using Insight.TelegramBot.Models; using Microsoft.Extensions.Logging; +using Nocr.TelegramClient.AppServices.Bots.MessageDispatcher; using Telegram.Bot; using Telegram.Bot.Types; -namespace Nocr.TelegramClient.AppServices; +namespace Nocr.TelegramClient.AppServices.Bots; public sealed class BotClient : Bot { @@ -14,7 +15,7 @@ public sealed class BotClient : Bot { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); } - + public override Task SendMessageAsync(TextMessage message, CancellationToken cancellationToken = default) { diff --git a/src/Nocr.TelegramClient.AppServices/Bots/MessageDispatcher/IMessageDispatcherHandler.cs b/src/Nocr.TelegramClient.AppServices/Bots/MessageDispatcher/IMessageDispatcherHandler.cs new file mode 100644 index 0000000..0c31b4c --- /dev/null +++ b/src/Nocr.TelegramClient.AppServices/Bots/MessageDispatcher/IMessageDispatcherHandler.cs @@ -0,0 +1,7 @@ +using Nocr.TelegramClient.Core.BackgroundJobs; + +namespace Nocr.TelegramClient.AppServices.Bots.MessageDispatcher; + +public interface IMessageDispatcherHandler : IRepeatableBackgroundServiceHandler +{ +} \ No newline at end of file diff --git a/src/Nocr.TelegramClient.AppServices/Bots/MessageDispatcher/IMessageDispatcherQueue.cs b/src/Nocr.TelegramClient.AppServices/Bots/MessageDispatcher/IMessageDispatcherQueue.cs new file mode 100644 index 0000000..aea6567 --- /dev/null +++ b/src/Nocr.TelegramClient.AppServices/Bots/MessageDispatcher/IMessageDispatcherQueue.cs @@ -0,0 +1,10 @@ +using Insight.TelegramBot.Models; + +namespace Nocr.TelegramClient.AppServices.Bots.MessageDispatcher; + +public interface IMessageDispatcherQueue +{ + public void Enqueue(BotMessage message); + + public bool TryDequeue(out BotMessage? message); +} \ No newline at end of file diff --git a/src/Nocr.TelegramClient.AppServices/Bots/MessageDispatcher/MessageDispatcherBackgroundService.cs b/src/Nocr.TelegramClient.AppServices/Bots/MessageDispatcher/MessageDispatcherBackgroundService.cs new file mode 100644 index 0000000..be71f5b --- /dev/null +++ b/src/Nocr.TelegramClient.AppServices/Bots/MessageDispatcher/MessageDispatcherBackgroundService.cs @@ -0,0 +1,12 @@ +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Nocr.TelegramClient.Core.BackgroundJobs; + +namespace Nocr.TelegramClient.AppServices.Bots.MessageDispatcher; + +public sealed class MessageDispatcherBackgroundService : RepeatableBackgroundService +{ + public MessageDispatcherBackgroundService(ILogger logger, IOptions options, IServiceProvider serviceProvider) : base(logger, options.Value, serviceProvider) + { + } +} \ No newline at end of file diff --git a/src/Nocr.TelegramClient.AppServices/Bots/MessageDispatcher/MessageDispatcherHandler.cs b/src/Nocr.TelegramClient.AppServices/Bots/MessageDispatcher/MessageDispatcherHandler.cs new file mode 100644 index 0000000..4898b3d --- /dev/null +++ b/src/Nocr.TelegramClient.AppServices/Bots/MessageDispatcher/MessageDispatcherHandler.cs @@ -0,0 +1,36 @@ +using Insight.TelegramBot; +using Insight.TelegramBot.Models; +using Microsoft.Extensions.Logging; +using Telegram.Bot.Types; + +namespace Nocr.TelegramClient.AppServices.Bots.MessageDispatcher; + +public sealed class MessageDispatcherHandler : IMessageDispatcherHandler +{ + private readonly ILogger _logger; + private readonly IBot _bot; + private readonly IMessageDispatcherQueue _queue; + + public MessageDispatcherHandler(ILogger logger, IBot bot, IMessageDispatcherQueue queue) + { + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + _bot = bot ?? throw new ArgumentNullException(nameof(bot)); + _queue = queue ?? throw new ArgumentNullException(nameof(queue)); + } + + public async Task Handle(CancellationToken cancellationToken = default) + { + if (_queue.TryDequeue(out var message)) + { + switch (message) + { + case TextMessage tm: + await _bot.SendMessageAsync(tm, cancellationToken); + break; + default: + _logger.LogWarning("Dequeued message has unsupported type: {Type}", typeof(Message).FullName); + break; + } + } + } +} \ No newline at end of file diff --git a/src/Nocr.TelegramClient.AppServices/Bots/MessageDispatcher/MessageDispatcherOptions.cs b/src/Nocr.TelegramClient.AppServices/Bots/MessageDispatcher/MessageDispatcherOptions.cs new file mode 100644 index 0000000..6895b85 --- /dev/null +++ b/src/Nocr.TelegramClient.AppServices/Bots/MessageDispatcher/MessageDispatcherOptions.cs @@ -0,0 +1,7 @@ +using Nocr.TelegramClient.Core.BackgroundJobs; + +namespace Nocr.TelegramClient.AppServices.Bots.MessageDispatcher; + +public class MessageDispatcherOptions : RepeatableServiceOptions +{ +} \ No newline at end of file diff --git a/src/Nocr.TelegramClient.AppServices/Bots/MessageDispatcher/MessageDispatcherQueue.cs b/src/Nocr.TelegramClient.AppServices/Bots/MessageDispatcher/MessageDispatcherQueue.cs new file mode 100644 index 0000000..1849f42 --- /dev/null +++ b/src/Nocr.TelegramClient.AppServices/Bots/MessageDispatcher/MessageDispatcherQueue.cs @@ -0,0 +1,19 @@ +using System.Collections.Concurrent; +using Insight.TelegramBot.Models; + +namespace Nocr.TelegramClient.AppServices.Bots.MessageDispatcher; + +public sealed class MessageDispatcherQueue : IMessageDispatcherQueue +{ + private readonly ConcurrentQueue _queue = new(); + + public void Enqueue(BotMessage message) + { + _queue.Enqueue(message); + } + + public bool TryDequeue(out BotMessage? message) + { + return _queue.TryDequeue(out message); + } +} \ No newline at end of file diff --git a/src/Nocr.TelegramClient.AppServices/Handlers/Messages/StartMessage/StartMessageHandler.cs b/src/Nocr.TelegramClient.AppServices/Handlers/Messages/StartMessage/StartMessageHandler.cs index dabad00..ac74e33 100644 --- a/src/Nocr.TelegramClient.AppServices/Handlers/Messages/StartMessage/StartMessageHandler.cs +++ b/src/Nocr.TelegramClient.AppServices/Handlers/Messages/StartMessage/StartMessageHandler.cs @@ -1,18 +1,19 @@ using Insight.TelegramBot; using Insight.TelegramBot.Handling.Handlers; using Insight.TelegramBot.Models; +using Nocr.TelegramClient.AppServices.Bots.MessageDispatcher; using Telegram.Bot.Types; using Telegram.Bot.Types.Enums; -namespace Nocr.TelegramClient.AppServices.Handlers.Messages.StartMesage; +namespace Nocr.TelegramClient.AppServices.Handlers.Messages.StartMessage; public class StartMessageHandler : IMatchingUpdateHandler { - private readonly IBot _bot; + private readonly IMessageDispatcherQueue _messageQueue; - public StartMessageHandler(IBot bot) + public StartMessageHandler(IMessageDispatcherQueue messageQueue) { - _bot = bot ?? throw new ArgumentNullException(nameof(bot)); + _messageQueue = messageQueue ?? throw new ArgumentNullException(nameof(messageQueue)); } public Task Handle(Update update, CancellationToken cancellationToken = default) @@ -24,6 +25,7 @@ public class StartMessageHandler : IMatchingUpdateHandler ParseMode = ParseMode.Html }; - return _bot.SendMessageAsync(message, cancellationToken); + _messageQueue.Enqueue(message); + return Task.CompletedTask; } } \ No newline at end of file diff --git a/src/Nocr.TelegramClient.AppServices/Handlers/Messages/StartMessage/StartMessageMatcher.cs b/src/Nocr.TelegramClient.AppServices/Handlers/Messages/StartMessage/StartMessageMatcher.cs index 72ba13e..bb4a41b 100644 --- a/src/Nocr.TelegramClient.AppServices/Handlers/Messages/StartMessage/StartMessageMatcher.cs +++ b/src/Nocr.TelegramClient.AppServices/Handlers/Messages/StartMessage/StartMessageMatcher.cs @@ -1,6 +1,6 @@ using Insight.TelegramBot.Handling.Matchers.TextMatchers; -namespace Nocr.TelegramClient.AppServices.Handlers.Messages.StartMesage; +namespace Nocr.TelegramClient.AppServices.Handlers.Messages.StartMessage; public sealed class StartMessageMatcher : TextStartWithUpdateMatcher { diff --git a/src/Nocr.TelegramClient.AppServices/Handlers/Messages/SubscribeMessage/SubscribeMessageHandler.cs b/src/Nocr.TelegramClient.AppServices/Handlers/Messages/SubscribeMessage/SubscribeMessageHandler.cs index 2021218..db892d2 100644 --- a/src/Nocr.TelegramClient.AppServices/Handlers/Messages/SubscribeMessage/SubscribeMessageHandler.cs +++ b/src/Nocr.TelegramClient.AppServices/Handlers/Messages/SubscribeMessage/SubscribeMessageHandler.cs @@ -1,8 +1,8 @@ using System.Text.RegularExpressions; using Insight.TelegramBot; using Insight.TelegramBot.Handling.Handlers; -using Insight.TelegramBot.Handling.Matchers.TextMatchers; using Insight.TelegramBot.Models; +using Nocr.TelegramClient.AppServices.Bots.MessageDispatcher; using Nocr.TelegramClient.AppServices.Users; using Nocr.TextMatcher.Api.Contracts.TextMatches; using Nocr.TextMatcher.Api.Contracts.TextMatches.Requests; @@ -10,17 +10,9 @@ using Telegram.Bot.Types; namespace Nocr.TelegramClient.AppServices.Handlers.Messages.SubscribeMessage; -public sealed class SubscribeMessageMatcher : TextStartWithUpdateMatcher -{ - public SubscribeMessageMatcher() - { - Template = "/subscribe"; - } -} - public class SubscribeMessageHandler : IMatchingUpdateHandler { - private readonly IBot _bot; + private readonly IMessageDispatcherQueue _messageQueue; private readonly IUsersService _usersService; private readonly ITextMatchesController _textMatchesController; @@ -32,9 +24,10 @@ public class SubscribeMessageHandler : IMatchingUpdateHandler +{ + private readonly IMessageDispatcherQueue _messageQueue; + private readonly IUsersService _usersService; + private readonly ITextMatchesController _matchesController; + + public SubscriptionsMessageHandler(IMessageDispatcherQueue messageQueue, IUsersService usersService, + ITextMatchesController matchesController) + { + _messageQueue = messageQueue ?? throw new ArgumentNullException(nameof(messageQueue)); + _usersService = usersService ?? throw new ArgumentNullException(nameof(usersService)); + _matchesController = matchesController ?? throw new ArgumentNullException(nameof(matchesController)); + } + + public async Task Handle(Update update, CancellationToken cancellationToken = default) + { + var telegramId = update.Message.From.Id; + var user = await _usersService.GetOrCreate(telegramId, update.Message.From.Username, cancellationToken); + + var subscriptions = await _matchesController.GetByUserId(user.Id, cancellationToken); + + foreach (var subscription in subscriptions) + { + var textMessage = new TextMessage(telegramId) + { + Text = subscription.TextView(), + ParseMode = ParseMode.Html + }; + + _messageQueue.Enqueue(textMessage); + } + } +} \ No newline at end of file diff --git a/src/Nocr.TelegramClient.AppServices/Handlers/Messages/SubscriptionsMessage/SubscriptionsMessageMatcher.cs b/src/Nocr.TelegramClient.AppServices/Handlers/Messages/SubscriptionsMessage/SubscriptionsMessageMatcher.cs new file mode 100644 index 0000000..ec217de --- /dev/null +++ b/src/Nocr.TelegramClient.AppServices/Handlers/Messages/SubscriptionsMessage/SubscriptionsMessageMatcher.cs @@ -0,0 +1,11 @@ +using Insight.TelegramBot.Handling.Matchers.TextMatchers; + +namespace Nocr.TelegramClient.AppServices.Handlers.Messages.SubscriptionsMessage; + +public class SubscriptionsMessageMatcher : TextStartWithUpdateMatcher +{ + public SubscriptionsMessageMatcher() + { + Template = "/subscriptions"; + } +} \ No newline at end of file diff --git a/src/Nocr.TelegramClient.AppServices/Matches/TextMatchMatchedHandler.cs b/src/Nocr.TelegramClient.AppServices/Matches/Handlers/TextMatchMatchedHandler.cs similarity index 67% rename from src/Nocr.TelegramClient.AppServices/Matches/TextMatchMatchedHandler.cs rename to src/Nocr.TelegramClient.AppServices/Matches/Handlers/TextMatchMatchedHandler.cs index e13745b..e1f3b41 100644 --- a/src/Nocr.TelegramClient.AppServices/Matches/TextMatchMatchedHandler.cs +++ b/src/Nocr.TelegramClient.AppServices/Matches/Handlers/TextMatchMatchedHandler.cs @@ -8,7 +8,7 @@ using Nocr.Users.Api.Contracts.Users; using Rebus.Handlers; using Telegram.Bot.Types.Enums; -namespace Nocr.TelegramClient.AppServices.Matches; +namespace Nocr.TelegramClient.AppServices.Matches.Handlers; public class TextMatchMatchedHandler : IHandleMessages { @@ -41,29 +41,13 @@ public class TextMatchMatchedHandler : IHandleMessages return; } - var fromUsername = string.IsNullOrWhiteSpace(message.FromUsername) ? "anonymous" : message.FromUsername; + var fromUsername = string.IsNullOrWhiteSpace(message.From) ? "anonymous" : message.From; var textMessage = new TextMessage(long.Parse(identity.Identity)) { - Text = - $"[{message.PublishedDateTime:MM.dd.yyyy HH:mm:ss}] Найдено совпадение.
Тип совпадения: '{GetTextMatchRule((TextMatchRule)message.Rule)}'
Шаблон: '{message.Template}'
{fromUsername} в @{message.ChatUsername}: {message.Text}", + Text = $"[{message.PublishedDateTime:MM.dd.yyyy HH:mm:ss}] Найдено совпадение.\nТип совпадения: '{((TextMatchRule)message.Rule).TextView()}'\nШаблон: '{message.Template}'\n{fromUsername} в @{message.ChatUsername}: {message.Text}", ParseMode = ParseMode.Html }; await _bot.SendMessageAsync(textMessage); } - - private string GetTextMatchRule(TextMatchRule rule) - { - switch (rule) - { - case TextMatchRule.Full: - return "Полное"; - case TextMatchRule.AllWords: - return "Все слова из списка"; - case TextMatchRule.AnyWord: - return "Одно слово из списка"; - default: - throw new IndexOutOfRangeException(nameof(rule)); - } - } } \ No newline at end of file diff --git a/src/Nocr.TelegramClient.AppServices/Matches/TextMatchExtensions.cs b/src/Nocr.TelegramClient.AppServices/Matches/TextMatchExtensions.cs new file mode 100644 index 0000000..72075ec --- /dev/null +++ b/src/Nocr.TelegramClient.AppServices/Matches/TextMatchExtensions.cs @@ -0,0 +1,32 @@ +using Nocr.TextMatcher.Api.Contracts.TextMatches; +using Nocr.TextMatcher.Api.Contracts.TextMatches.Dto; + +namespace Nocr.TelegramClient.AppServices.Matches; + +public static class TextMatchExtensions +{ + public static string TextView(this TextMatchData textMatch) + { + var activeText = textMatch.Active ? "Активна" : "Не активна"; + var activeCommandText = textMatch.Active + ? $"Деактивировать: /deactivate_{textMatch.Id}" + : $"Активировать: /activate_{textMatch.Id}"; + var deleteCommandText = $"Удалить: /delete_subscription_{textMatch.Id}"; + return $"[{textMatch.Id}] (@{textMatch.ChatUsername}) {activeText}: '{textMatch.Rule.TextView()}' > '{textMatch.Template}'\n{activeCommandText}\n{deleteCommandText}"; + } + + public static string TextView(this TextMatchRule rule) + { + switch (rule) + { + case TextMatchRule.Full: + return "Полное"; + case TextMatchRule.AllWords: + return "Все слова из списка"; + case TextMatchRule.AnyWord: + return "Одно слово из списка"; + default: + throw new IndexOutOfRangeException(nameof(rule)); + } + } +} \ No newline at end of file diff --git a/src/Nocr.TelegramClient.AppServices/Nocr.TelegramClient.AppServices.csproj b/src/Nocr.TelegramClient.AppServices/Nocr.TelegramClient.AppServices.csproj index f92f7c1..0f7f8fc 100644 --- a/src/Nocr.TelegramClient.AppServices/Nocr.TelegramClient.AppServices.csproj +++ b/src/Nocr.TelegramClient.AppServices/Nocr.TelegramClient.AppServices.csproj @@ -4,18 +4,18 @@ false - - - - - - - - - + + + + + + + + + - + diff --git a/src/Nocr.TelegramClient.AppServices/ServiceCollectionExtensions.cs b/src/Nocr.TelegramClient.AppServices/ServiceCollectionExtensions.cs index c2c3dd7..f5a62d8 100644 --- a/src/Nocr.TelegramClient.AppServices/ServiceCollectionExtensions.cs +++ b/src/Nocr.TelegramClient.AppServices/ServiceCollectionExtensions.cs @@ -1,7 +1,10 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; +using Nocr.TelegramClient.AppServices.Bots; +using Nocr.TelegramClient.AppServices.Bots.MessageDispatcher; using Nocr.TelegramClient.AppServices.Matches; +using Nocr.TelegramClient.AppServices.Matches.Handlers; using Nocr.TelegramClient.AppServices.Options; using Nocr.TelegramClient.AppServices.Users; using Nocr.TextMatcher.Api.Contracts.TextMatches; @@ -44,6 +47,11 @@ public static class ServiceCollectionExtensions services.AddScoped(); + services.Configure(configuration.GetSection(nameof(MessageDispatcherOptions))); + services.AddSingleton(); + services.AddScoped(); + services.AddHostedService(); + return services; } } \ No newline at end of file diff --git a/src/Nocr.TelegramClient.Core/BackgroundJobs/IRepeatableBackgroundServiceHandler.cs b/src/Nocr.TelegramClient.Core/BackgroundJobs/IRepeatableBackgroundServiceHandler.cs new file mode 100644 index 0000000..a7e11ec --- /dev/null +++ b/src/Nocr.TelegramClient.Core/BackgroundJobs/IRepeatableBackgroundServiceHandler.cs @@ -0,0 +1,6 @@ +namespace Nocr.TelegramClient.Core.BackgroundJobs; + +public interface IRepeatableBackgroundServiceHandler +{ + Task Handle(CancellationToken cancellationToken = default); +} \ No newline at end of file diff --git a/src/Nocr.TelegramClient.Core/BackgroundJobs/RepeatableBackgroundService.cs b/src/Nocr.TelegramClient.Core/BackgroundJobs/RepeatableBackgroundService.cs new file mode 100644 index 0000000..9cabde7 --- /dev/null +++ b/src/Nocr.TelegramClient.Core/BackgroundJobs/RepeatableBackgroundService.cs @@ -0,0 +1,42 @@ +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; + +namespace Nocr.TelegramClient.Core.BackgroundJobs; + +public abstract class RepeatableBackgroundService : BackgroundService + where THandler : IRepeatableBackgroundServiceHandler + where TOptions : RepeatableServiceOptions + +{ + private readonly ILogger> _logger; + private readonly TOptions _options; + private readonly IServiceProvider _serviceProvider; + + protected RepeatableBackgroundService(ILogger> logger, TOptions options, IServiceProvider serviceProvider) + { + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + _options = options ?? throw new ArgumentNullException(nameof(options)); + _serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider)); + } + + protected override async Task ExecuteAsync(CancellationToken stoppingToken) + { + while (!stoppingToken.IsCancellationRequested) + { + try + { + using var scope = _serviceProvider.CreateScope(); + var handler = scope.ServiceProvider.GetRequiredService(); + await handler.Handle(stoppingToken); + + await Task.Delay(_options.Interval, stoppingToken); + } + catch (Exception ex) + { + _logger.LogCritical(ex, "Failed to process..."); + await Task.Delay(_options.ExceptionInterval, stoppingToken); + } + } + } +} \ No newline at end of file diff --git a/src/Nocr.TelegramClient.Core/BackgroundJobs/RepeatableServiceOptions.cs b/src/Nocr.TelegramClient.Core/BackgroundJobs/RepeatableServiceOptions.cs new file mode 100644 index 0000000..efc837b --- /dev/null +++ b/src/Nocr.TelegramClient.Core/BackgroundJobs/RepeatableServiceOptions.cs @@ -0,0 +1,8 @@ +namespace Nocr.TelegramClient.Core.BackgroundJobs; + +public abstract class RepeatableServiceOptions +{ + public TimeSpan Interval { get; set; } = TimeSpan.FromSeconds(60); + + public TimeSpan ExceptionInterval { get; set; } = TimeSpan.FromSeconds(300); +} \ No newline at end of file diff --git a/src/Nocr.TelegramClient.Core/Nocr.TelegramClient.Core.csproj b/src/Nocr.TelegramClient.Core/Nocr.TelegramClient.Core.csproj index 2ef1a36..5109320 100644 --- a/src/Nocr.TelegramClient.Core/Nocr.TelegramClient.Core.csproj +++ b/src/Nocr.TelegramClient.Core/Nocr.TelegramClient.Core.csproj @@ -1 +1,5 @@ - + + + + + \ No newline at end of file diff --git a/src/Nocr.TelegramClient.Host/Infrastructure/Startup.cs b/src/Nocr.TelegramClient.Host/Infrastructure/Startup.cs index bbea9c3..082b048 100644 --- a/src/Nocr.TelegramClient.Host/Infrastructure/Startup.cs +++ b/src/Nocr.TelegramClient.Host/Infrastructure/Startup.cs @@ -3,6 +3,7 @@ using Insight.TelegramBot.Hosting.DependencyInjection.Infrastructure; using Insight.TelegramBot.Hosting.Polling.ExceptionHandlers; using Microsoft.Extensions.Options; using Nocr.TelegramClient.AppServices; +using Nocr.TelegramClient.AppServices.Bots; using Nocr.TelegramClient.Core.Dates; using Nocr.TelegramClient.Core.Options; using Rebus.Bus; diff --git a/src/Nocr.TelegramClient.Host/appsettings.json b/src/Nocr.TelegramClient.Host/appsettings.json index 1b0eb19..979a5d0 100644 --- a/src/Nocr.TelegramClient.Host/appsettings.json +++ b/src/Nocr.TelegramClient.Host/appsettings.json @@ -13,5 +13,9 @@ "InputQueueName": "nocr.telegram.client.queue", "DirectExchangeName": "nocr.direct", "TopicsExchangeName": "nocr.topics" + }, + "MessageDispatcherOptions": { + "Interval": "00:00:00.050", + "ExceptionInterval": "00:00:30" } }