From 93aa82954380b1eca8883bff56a4a3871a9714c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D1=8B=D1=80=D1=86=D0=B5=D0=B2=20=D0=92=D0=B0=D0=B4?= =?UTF-8?q?=D0=B8=D0=BC=20=D0=98=D0=B3=D0=BE=D1=80=D0=B5=D0=B2=D0=B8=D1=87?= Date: Thu, 4 Jul 2024 21:50:20 +0300 Subject: [PATCH] It could be the brother of Option>.. --- crates/teloxide/examples/error_handler.rs | 29 ++++-------- crates/teloxide/src/dispatching/dispatcher.rs | 4 +- crates/teloxide/src/error_handlers.rs | 47 ++++++++----------- 3 files changed, 31 insertions(+), 49 deletions(-) diff --git a/crates/teloxide/examples/error_handler.rs b/crates/teloxide/examples/error_handler.rs index 3d66ce03..310fa465 100644 --- a/crates/teloxide/examples/error_handler.rs +++ b/crates/teloxide/examples/error_handler.rs @@ -59,29 +59,18 @@ async fn main() { .await; } -async fn error_handler(error: PublicError, deps: Option) { +async fn error_handler(error: PublicError, deps: DependencyMap) { /* - When the error is returned from one of the handlers, deps will contain actual initial_dependencies - - In this example it's not valuable to handle errors with no dependencies, so just log them and ignore - */ - if deps.is_none() { - log::error!("Error occured: {}", error); - return; - } - let deps = deps.unwrap(); - - /* - The Bot is always present in the dependencies, so it's safe to query it here - - Note that you can access only initial dependencies, such as: - - Bot - - Update - - Me - - and the ones you've provided to the Dispatcher's dependencies + When an error is occured in one of your handlers, you can access only initial dependencies, such as: + - Update + - Bot + - Me + - and the ones you've provided to the Dispatcher's dependencies at the beginning */ let bot: Arc = deps.get(); + // It worth to note that in case of UpdateListener::Error there will be no + // Update value let update: Arc = deps.get(); let chat_id = update.chat().map(|c| c.id); @@ -89,7 +78,7 @@ async fn error_handler(error: PublicError, deps: Option) { PublicError::Dummy => { // Some updates don't have a chat id if let Some(chat_id) = chat_id { - // TODO, maybe retry queue? + // TODO, maybe retry queue? backon? let _ = bot.send_message(chat_id, error.to_string()).await; } } diff --git a/crates/teloxide/src/dispatching/dispatcher.rs b/crates/teloxide/src/dispatching/dispatcher.rs index f2a8651c..ce68fd19 100644 --- a/crates/teloxide/src/dispatching/dispatcher.rs +++ b/crates/teloxide/src/dispatching/dispatcher.rs @@ -492,7 +492,7 @@ where worker.tx.send(upd).await.expect("TX is dead"); } - Err(err) => err_handler.clone().handle_error(err, None).await, + Err(err) => err_handler.clone().handle_error(err, self.dependencies.clone()).await, } } @@ -649,7 +649,7 @@ async fn handle_update( match handler.dispatch(deps.clone()).await { ControlFlow::Break(Ok(())) => {} - ControlFlow::Break(Err(err)) => error_handler.clone().handle_error(err, Some(deps)).await, + ControlFlow::Break(Err(err)) => error_handler.clone().handle_error(err, deps).await, ControlFlow::Continue(deps) => { let update = deps.get(); (default_handler)(update).await; diff --git a/crates/teloxide/src/error_handlers.rs b/crates/teloxide/src/error_handlers.rs index 4a500bb8..f86b988c 100644 --- a/crates/teloxide/src/error_handlers.rs +++ b/crates/teloxide/src/error_handlers.rs @@ -11,24 +11,16 @@ use futures::future::BoxFuture; /// overview](crate::dispatching). pub trait ErrorHandler { #[must_use] - fn handle_error( - self: Arc, - error: E, - deps: Option, - ) -> BoxFuture<'static, ()>; + fn handle_error(self: Arc, error: E, deps: DependencyMap) -> BoxFuture<'static, ()>; } impl ErrorHandler for F where - F: Fn(E, Option) -> Fut + Send + Sync + 'static, + F: Fn(E, DependencyMap) -> Fut + Send + Sync + 'static, E: Send + 'static, Fut: Future + Send, { - fn handle_error( - self: Arc, - error: E, - deps: Option, - ) -> BoxFuture<'static, ()> { + fn handle_error(self: Arc, error: E, deps: DependencyMap) -> BoxFuture<'static, ()> { Box::pin(async move { self(error, deps).await }) } } @@ -93,7 +85,7 @@ where { Box::pin(async move { if let Err(error) = self { - eh.handle_error(error, None).await; + eh.handle_error(error, DependencyMap::new()).await; } }) } @@ -108,9 +100,9 @@ where /// use dptree::di::DependencyMap; /// use teloxide::error_handlers::{ErrorHandler, IgnoringErrorHandler}; /// -/// IgnoringErrorHandler::new().handle_error((), None).await; -/// IgnoringErrorHandler::new().handle_error(404, None).await; -/// IgnoringErrorHandler::new().handle_error("error", None).await; +/// IgnoringErrorHandler::new().handle_error((), DependencyMap::new()).await; +/// IgnoringErrorHandler::new().handle_error(404, DependencyMap::new()).await; +/// IgnoringErrorHandler::new().handle_error("error", DependencyMap::new()).await; /// # } /// ``` #[derive(Clone, Copy)] @@ -124,7 +116,7 @@ impl IgnoringErrorHandler { } impl ErrorHandler for IgnoringErrorHandler { - fn handle_error(self: Arc, _: E, _: Option) -> BoxFuture<'static, ()> { + fn handle_error(self: Arc, _: E, _: DependencyMap) -> BoxFuture<'static, ()> { Box::pin(async {}) } } @@ -138,15 +130,17 @@ impl ErrorHandler for IgnoringErrorHandler { /// # async fn main_() { /// use std::convert::{Infallible, TryInto}; /// +/// use dptree::di::DependencyMap; /// use teloxide::error_handlers::{ErrorHandler, IgnoringErrorHandlerSafe}; /// /// let result: Result = "str".try_into(); /// match result { /// Ok(string) => println!("{}", string), -/// Err(inf) => IgnoringErrorHandlerSafe::new().handle_error(inf, None).await, +/// Err(inf) => IgnoringErrorHandlerSafe::new().handle_error(inf, DependencyMap::new()).await, /// } /// -/// IgnoringErrorHandlerSafe::new().handle_error(return, None).await; // return type of `return` is `!` (aka never) +/// IgnoringErrorHandlerSafe::new().handle_error(return, DependencyMap::new()).await; +/// // return type of `return` is `!` (aka never) /// # } /// ``` /// @@ -170,11 +164,7 @@ impl IgnoringErrorHandlerSafe { #[allow(unreachable_code)] impl ErrorHandler for IgnoringErrorHandlerSafe { - fn handle_error( - self: Arc, - _: Infallible, - _: Option, - ) -> BoxFuture<'static, ()> { + fn handle_error(self: Arc, _: Infallible, _: DependencyMap) -> BoxFuture<'static, ()> { Box::pin(async {}) } } @@ -185,11 +175,14 @@ impl ErrorHandler for IgnoringErrorHandlerSafe { /// ``` /// # #[tokio::main] /// # async fn main_() { +/// use dptree::di::DependencyMap; /// use teloxide::error_handlers::{ErrorHandler, LoggingErrorHandler}; /// -/// LoggingErrorHandler::new().handle_error((), None).await; -/// LoggingErrorHandler::with_custom_text("Omg1").handle_error(404, None).await; -/// LoggingErrorHandler::with_custom_text("Omg2").handle_error("Invalid data type!", None).await; +/// LoggingErrorHandler::new().handle_error((), DependencyMap::new()).await; +/// LoggingErrorHandler::with_custom_text("Omg1").handle_error(404, DependencyMap::new()).await; +/// LoggingErrorHandler::with_custom_text("Omg2") +/// .handle_error("Invalid data type!", DependencyMap::new()) +/// .await; /// # } /// ``` pub struct LoggingErrorHandler { @@ -220,7 +213,7 @@ impl ErrorHandler for LoggingErrorHandler where E: Debug, { - fn handle_error(self: Arc, error: E, _: Option) -> BoxFuture<'static, ()> { + fn handle_error(self: Arc, error: E, _: DependencyMap) -> BoxFuture<'static, ()> { log::error!("{text}: {:?}", error, text = self.text); Box::pin(async {}) }