From 6074ee83a1205556a5ead5cc4d9461f430a4b8aa Mon Sep 17 00:00:00 2001 From: XSilverTH Date: Thu, 18 Dec 2025 17:29:46 +0330 Subject: [PATCH 1/3] Make the UpdateRecevier not wait for each handler --- Telegrator/Polling/ReactiveUpdateReceiver.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Telegrator/Polling/ReactiveUpdateReceiver.cs b/Telegrator/Polling/ReactiveUpdateReceiver.cs index a4d5b68..d6a0b72 100644 --- a/Telegrator/Polling/ReactiveUpdateReceiver.cs +++ b/Telegrator/Polling/ReactiveUpdateReceiver.cs @@ -63,11 +63,12 @@ namespace Telegrator.Polling try { request.Offset = update.Id + 1; - await updateHandler.HandleUpdateAsync(Client, update, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); + _ = updateHandler.HandleUpdateAsync(Client, update, cancellationToken); } catch (Exception exception2) { - await updateHandler.HandleErrorAsync(Client, exception2, HandleErrorSource.HandleUpdateError, cancellationToken).ConfigureAwait(false); + await updateHandler.HandleErrorAsync(Client, exception2, + HandleErrorSource.HandleUpdateError, cancellationToken).ConfigureAwait(false); } } } -- 2.43.0 From de397b95f61f60d8e4047f001c940763e780b051 Mon Sep 17 00:00:00 2001 From: XSilverTH Date: Mon, 29 Dec 2025 16:39:09 +0330 Subject: [PATCH 2/3] Move initiating handlers as a background task from ReactiveUpdateReceiver to UpdateHandlersPool --- Telegrator/Polling/ReactiveUpdateReceiver.cs | 8 +- Telegrator/Polling/UpdateHandlersPool.cs | 95 +++++++++++--------- 2 files changed, 59 insertions(+), 44 deletions(-) diff --git a/Telegrator/Polling/ReactiveUpdateReceiver.cs b/Telegrator/Polling/ReactiveUpdateReceiver.cs index d6a0b72..082b281 100644 --- a/Telegrator/Polling/ReactiveUpdateReceiver.cs +++ b/Telegrator/Polling/ReactiveUpdateReceiver.cs @@ -1,4 +1,4 @@ -using Telegram.Bot; +using Telegram.Bot; using Telegram.Bot.Polling; using Telegram.Bot.Requests; using Telegram.Bot.Types; @@ -6,12 +6,12 @@ using Telegram.Bot.Types; namespace Telegrator.Polling { /// - /// Reactive implementation of for polling updates from Telegram. + /// Reactive update receiver for polling updates from Telegram. /// Provides custom update receiving logic with error handling and configuration options. /// /// The Telegram bot client for making API requests. /// Optional receiver options for configuring update polling behavior. - public class ReactiveUpdateReceiver(ITelegramBotClient client, ReceiverOptions? options) : IUpdateReceiver + public class ReactiveUpdateReceiver(ITelegramBotClient client, ReceiverOptions? options) { /// /// Gets the receiver options for configuring update polling behavior. @@ -63,7 +63,7 @@ namespace Telegrator.Polling try { request.Offset = update.Id + 1; - _ = updateHandler.HandleUpdateAsync(Client, update, cancellationToken); + await updateHandler.HandleUpdateAsync(Client, update, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } catch (Exception exception2) { diff --git a/Telegrator/Polling/UpdateHandlersPool.cs b/Telegrator/Polling/UpdateHandlersPool.cs index 5b3dd49..8b1cbb3 100644 --- a/Telegrator/Polling/UpdateHandlersPool.cs +++ b/Telegrator/Polling/UpdateHandlersPool.cs @@ -61,57 +61,72 @@ namespace Telegrator.Polling /// public async Task Enqueue(IEnumerable handlers) { - Result? lastResult = null; - foreach (DescribedHandlerInfo handlerInfo in handlers) + if (ExecutingHandlersSemaphore != null) { - if (lastResult?.NextType != null) - { - if (lastResult.NextType != handlerInfo.From.HandlerType) - continue; - } - - if (ExecutingHandlersSemaphore != null) - { - await ExecutingHandlersSemaphore.WaitAsync().ConfigureAwait(false); - } + await ExecutingHandlersSemaphore.WaitAsync().ConfigureAwait(false); + } + // Offload the entire processing of this update's handlers to a background task. + // This allows the Receiver to continue polling for NEW updates immediately, + // while this update acts as a self-contained unit of work. + _ = Task.Run(async () => + { try { - Alligator.LogDebug("Described handler '{0}' (Update {1})", handlerInfo.DisplayString, handlerInfo.HandlingUpdate.Id); - HandlerExecuting?.Invoke(handlerInfo); - - using (UpdateHandlerBase instance = handlerInfo.HandlerInstance) + Result? lastResult = null; + foreach (DescribedHandlerInfo handlerInfo in handlers) { - Task task = instance.Execute(handlerInfo); - HandlerEnqueued?.Invoke(handlerInfo); + if (lastResult?.NextType != null) + { + if (lastResult.NextType != handlerInfo.From.HandlerType) + continue; + } - await task.ConfigureAwait(false); - lastResult = task.Result; - ExecutingHandlersSemaphore?.Release(1); - } + try + { + Alligator.LogDebug("Described handler '{0}' (Update {1})", handlerInfo.DisplayString, + handlerInfo.HandlingUpdate.Id); + HandlerExecuting?.Invoke(handlerInfo); - if (lastResult.RouteNext) - { - Alligator.LogTrace("Handler '{0}' requested route continuation (Update {1})", handlerInfo.DisplayString, handlerInfo.HandlingUpdate.Id); + using (UpdateHandlerBase instance = handlerInfo.HandlerInstance) + { + Task task = instance.Execute(handlerInfo); + HandlerEnqueued?.Invoke(handlerInfo); + + await task.ConfigureAwait(false); + lastResult = task.Result; + } + + if (lastResult.RouteNext) + { + Alligator.LogTrace("Handler '{0}' requested route continuation (Update {1})", + handlerInfo.DisplayString, handlerInfo.HandlingUpdate.Id); + } + } + catch (NotImplementedException) + { + _ = 0xBAD + 0xC0DE; + } + catch (OperationCanceledException) + { + _ = 0xBAD + 0xC0DE; + break; + } + catch (Exception ex) + { + Alligator.LogError("Failed to process handler '{0}' (Update {1})", exception: ex, + handlerInfo.DisplayString, handlerInfo.HandlingUpdate.Id); + } + + if (lastResult != null && !lastResult.RouteNext) + break; } } - catch (NotImplementedException) + finally { - _ = 0xBAD + 0xC0DE; + ExecutingHandlersSemaphore?.Release(1); } - catch (OperationCanceledException) - { - _ = 0xBAD + 0xC0DE; - break; - } - catch (Exception ex) - { - Alligator.LogError("Failed to process handler '{0}' (Update {1})", exception: ex, handlerInfo.DisplayString, handlerInfo.HandlingUpdate.Id); - } - - if (lastResult != null && !lastResult.RouteNext) - break; - } + }, GlobalCancellationToken); } /// -- 2.43.0 From 00842216a1ce1e344b63595bfc681270e0c6fb9a Mon Sep 17 00:00:00 2001 From: XSilverTH Date: Mon, 29 Dec 2025 16:53:32 +0330 Subject: [PATCH 3/3] Revert: accidental commit of extra changes --- Telegrator/Polling/ReactiveUpdateReceiver.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Telegrator/Polling/ReactiveUpdateReceiver.cs b/Telegrator/Polling/ReactiveUpdateReceiver.cs index 082b281..4f4cf1f 100644 --- a/Telegrator/Polling/ReactiveUpdateReceiver.cs +++ b/Telegrator/Polling/ReactiveUpdateReceiver.cs @@ -6,12 +6,12 @@ using Telegram.Bot.Types; namespace Telegrator.Polling { /// - /// Reactive update receiver for polling updates from Telegram. - /// Provides custom update receiving logic with error handling and configuration options. + /// Reactive implementation of for polling updates from Telegram. + /// /// Provides custom update receiving logic with error handling and configuration options. /// /// The Telegram bot client for making API requests. /// Optional receiver options for configuring update polling behavior. - public class ReactiveUpdateReceiver(ITelegramBotClient client, ReceiverOptions? options) + public class ReactiveUpdateReceiver(ITelegramBotClient client, ReceiverOptions? options) : IUpdateReceiver { /// /// Gets the receiver options for configuring update polling behavior. -- 2.43.0