mirror of
https://github.com/teloxide/teloxide.git
synced 2025-04-13 09:24:34 +02:00
Allow optional deps in ErrorHandler::handle_error
This commit is contained in:
parent
1e8636a76a
commit
6e74e5e087
3 changed files with 47 additions and 85 deletions
crates/teloxide
|
@ -59,7 +59,18 @@ async fn main() {
|
|||
.await;
|
||||
}
|
||||
|
||||
async fn error_handler(deps: DependencyMap, error: PublicError) {
|
||||
async fn error_handler(error: PublicError, deps: Option<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
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ use crate::{
|
|||
distribution::default_distribution_function, DefaultKey, DpHandlerDescription,
|
||||
ShutdownToken,
|
||||
},
|
||||
error_handlers::{ErrorHandlerExt, LoggingErrorHandler},
|
||||
error_handlers::{ErrorHandler, LoggingErrorHandler},
|
||||
requests::{Request, Requester},
|
||||
types::{Update, UpdateKind},
|
||||
update_listeners::{self, UpdateListener},
|
||||
|
@ -40,7 +40,7 @@ pub struct DispatcherBuilder<R, Err, Key> {
|
|||
dependencies: DependencyMap,
|
||||
handler: Arc<UpdateHandler<Err>>,
|
||||
default_handler: DefaultHandler,
|
||||
error_handler: Arc<dyn ErrorHandlerExt<Err> + Send + Sync>,
|
||||
error_handler: Arc<dyn ErrorHandler<Err> + Send + Sync>,
|
||||
ctrlc_handler: bool,
|
||||
distribution_f: fn(&Update) -> Option<Key>,
|
||||
worker_queue_size: usize,
|
||||
|
@ -75,8 +75,8 @@ where
|
|||
///
|
||||
/// By default, it is [`LoggingErrorHandler`].
|
||||
#[must_use]
|
||||
pub fn error_handler(self, handler: Arc<dyn ErrorHandlerExt<Err> + Send + Sync>) -> Self {
|
||||
Self { error_handler: handler, ..self }
|
||||
pub fn error_handler(self, error_handler: Arc<dyn ErrorHandler<Err> + Send + Sync>) -> Self {
|
||||
Self { error_handler, ..self }
|
||||
}
|
||||
|
||||
/// Specifies dependencies that can be used inside of handlers.
|
||||
|
@ -265,7 +265,7 @@ pub struct Dispatcher<R, Err, Key> {
|
|||
// The default TX part that consume updates concurrently.
|
||||
default_worker: Option<Worker>,
|
||||
|
||||
error_handler: Arc<dyn ErrorHandlerExt<Err> + Send + Sync>,
|
||||
error_handler: Arc<dyn ErrorHandler<Err> + Send + Sync>,
|
||||
|
||||
state: ShutdownToken,
|
||||
}
|
||||
|
@ -356,7 +356,7 @@ where
|
|||
update_listener_error_handler: Arc<Eh>,
|
||||
) where
|
||||
UListener: UpdateListener + 'a,
|
||||
Eh: ErrorHandlerExt<UListener::Err> + 'a,
|
||||
Eh: ErrorHandler<UListener::Err> + 'a,
|
||||
UListener::Err: Debug,
|
||||
{
|
||||
self.try_dispatch_with_listener(update_listener, update_listener_error_handler)
|
||||
|
@ -378,7 +378,7 @@ where
|
|||
) -> Result<(), R::Err>
|
||||
where
|
||||
UListener: UpdateListener + 'a,
|
||||
Eh: ErrorHandlerExt<UListener::Err> + 'a,
|
||||
Eh: ErrorHandler<UListener::Err> + 'a,
|
||||
UListener::Err: Debug,
|
||||
{
|
||||
// FIXME: there should be a way to check if dependency is already inserted
|
||||
|
@ -443,7 +443,7 @@ where
|
|||
update: Result<Update, LErr>,
|
||||
err_handler: &Arc<LErrHandler>,
|
||||
) where
|
||||
LErrHandler: ErrorHandlerExt<LErr>,
|
||||
LErrHandler: ErrorHandler<LErr>,
|
||||
{
|
||||
match update {
|
||||
Ok(upd) => {
|
||||
|
@ -492,7 +492,7 @@ where
|
|||
|
||||
worker.tx.send(upd).await.expect("TX is dead");
|
||||
}
|
||||
Err(err) => err_handler.clone().handle_error_with_deps(DependencyMap::new(), err).await,
|
||||
Err(err) => err_handler.clone().handle_error(err, None).await,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -572,7 +572,7 @@ fn spawn_worker<Err>(
|
|||
deps: DependencyMap,
|
||||
handler: Arc<UpdateHandler<Err>>,
|
||||
default_handler: DefaultHandler,
|
||||
error_handler: Arc<dyn ErrorHandlerExt<Err> + Send + Sync>,
|
||||
error_handler: Arc<dyn ErrorHandler<Err> + Send + Sync>,
|
||||
current_number_of_active_workers: Arc<AtomicU32>,
|
||||
max_number_of_active_workers: Arc<AtomicU32>,
|
||||
queue_size: usize,
|
||||
|
@ -613,7 +613,7 @@ fn spawn_default_worker<Err>(
|
|||
deps: DependencyMap,
|
||||
handler: Arc<UpdateHandler<Err>>,
|
||||
default_handler: DefaultHandler,
|
||||
error_handler: Arc<dyn ErrorHandlerExt<Err> + Send + Sync>,
|
||||
error_handler: Arc<dyn ErrorHandler<Err> + Send + Sync>,
|
||||
queue_size: usize,
|
||||
) -> Worker
|
||||
where
|
||||
|
@ -640,7 +640,7 @@ async fn handle_update<Err>(
|
|||
deps: Arc<DependencyMap>,
|
||||
handler: Arc<UpdateHandler<Err>>,
|
||||
default_handler: DefaultHandler,
|
||||
error_handler: Arc<dyn ErrorHandlerExt<Err> + Send + Sync>,
|
||||
error_handler: Arc<dyn ErrorHandler<Err> + Send + Sync>,
|
||||
) where
|
||||
Err: Send + Sync + 'static,
|
||||
{
|
||||
|
@ -649,9 +649,7 @@ async fn handle_update<Err>(
|
|||
|
||||
match handler.dispatch(deps.clone()).await {
|
||||
ControlFlow::Break(Ok(())) => {}
|
||||
ControlFlow::Break(Err(err)) => {
|
||||
error_handler.clone().handle_error_with_deps(deps, err).await
|
||||
}
|
||||
ControlFlow::Break(Err(err)) => error_handler.clone().handle_error(err, Some(deps)).await,
|
||||
ControlFlow::Continue(deps) => {
|
||||
let update = deps.get();
|
||||
(default_handler)(update).await;
|
||||
|
|
|
@ -5,48 +5,31 @@ use std::{convert::Infallible, fmt::Debug, future::Future, sync::Arc};
|
|||
use dptree::di::DependencyMap;
|
||||
use futures::future::BoxFuture;
|
||||
|
||||
/// An asynchronous handler of an error.
|
||||
/// An asynchronous handler of an error with dependencies
|
||||
///
|
||||
/// See [the module-level documentation for the design
|
||||
/// overview](crate::dispatching).
|
||||
pub trait ErrorHandler<E> {
|
||||
#[must_use]
|
||||
fn handle_error(self: Arc<Self>, error: E) -> BoxFuture<'static, ()>;
|
||||
fn handle_error(
|
||||
self: Arc<Self>,
|
||||
error: E,
|
||||
deps: Option<DependencyMap>,
|
||||
) -> BoxFuture<'static, ()>;
|
||||
}
|
||||
|
||||
impl<E, F, Fut> ErrorHandler<E> for F
|
||||
where
|
||||
F: Fn(E) -> Fut + Send + Sync + 'static,
|
||||
F: Fn(E, Option<DependencyMap>) -> Fut + Send + Sync + 'static,
|
||||
E: Send + 'static,
|
||||
Fut: Future<Output = ()> + Send,
|
||||
{
|
||||
fn handle_error(self: Arc<Self>, error: E) -> BoxFuture<'static, ()> {
|
||||
Box::pin(async move { self(error).await })
|
||||
}
|
||||
}
|
||||
|
||||
/// An asynchronous handler of an error with dependencies
|
||||
pub trait ErrorHandlerExt<E> {
|
||||
#[must_use]
|
||||
fn handle_error_with_deps(
|
||||
fn handle_error(
|
||||
self: Arc<Self>,
|
||||
deps: DependencyMap,
|
||||
error: E,
|
||||
) -> BoxFuture<'static, ()>;
|
||||
}
|
||||
|
||||
impl<E, F, Fut> ErrorHandlerExt<E> for F
|
||||
where
|
||||
F: Fn(DependencyMap, E) -> Fut + Send + Sync + 'static,
|
||||
E: Send + 'static,
|
||||
Fut: Future<Output = ()> + Send,
|
||||
{
|
||||
fn handle_error_with_deps(
|
||||
self: Arc<Self>,
|
||||
deps: DependencyMap,
|
||||
error: E,
|
||||
deps: Option<DependencyMap>,
|
||||
) -> BoxFuture<'static, ()> {
|
||||
Box::pin(async move { self(deps, error).await })
|
||||
Box::pin(async move { self(error, deps).await })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,7 +93,7 @@ where
|
|||
{
|
||||
Box::pin(async move {
|
||||
if let Err(error) = self {
|
||||
eh.handle_error(error).await;
|
||||
eh.handle_error(error, None).await;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -122,11 +105,12 @@ where
|
|||
/// ```
|
||||
/// # #[tokio::main]
|
||||
/// # async fn main_() {
|
||||
/// use dptree::di::DependencyMap;
|
||||
/// use teloxide::error_handlers::{ErrorHandler, IgnoringErrorHandler};
|
||||
///
|
||||
/// IgnoringErrorHandler::new().handle_error(()).await;
|
||||
/// IgnoringErrorHandler::new().handle_error(404).await;
|
||||
/// IgnoringErrorHandler::new().handle_error("error").await;
|
||||
/// IgnoringErrorHandler::new().handle_error((), None).await;
|
||||
/// IgnoringErrorHandler::new().handle_error(404, None).await;
|
||||
/// IgnoringErrorHandler::new().handle_error("error", None).await;
|
||||
/// # }
|
||||
/// ```
|
||||
#[derive(Clone, Copy)]
|
||||
|
@ -140,17 +124,7 @@ impl IgnoringErrorHandler {
|
|||
}
|
||||
|
||||
impl<E> ErrorHandler<E> for IgnoringErrorHandler {
|
||||
fn handle_error(self: Arc<Self>, _: E) -> BoxFuture<'static, ()> {
|
||||
Box::pin(async {})
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> ErrorHandlerExt<E> for IgnoringErrorHandler {
|
||||
fn handle_error_with_deps(
|
||||
self: Arc<Self>,
|
||||
_deps: DependencyMap,
|
||||
_: E,
|
||||
) -> BoxFuture<'static, ()> {
|
||||
fn handle_error(self: Arc<Self>, _: E, _: Option<DependencyMap>) -> BoxFuture<'static, ()> {
|
||||
Box::pin(async {})
|
||||
}
|
||||
}
|
||||
|
@ -196,17 +170,10 @@ impl IgnoringErrorHandlerSafe {
|
|||
|
||||
#[allow(unreachable_code)]
|
||||
impl ErrorHandler<Infallible> for IgnoringErrorHandlerSafe {
|
||||
fn handle_error(self: Arc<Self>, _: Infallible) -> BoxFuture<'static, ()> {
|
||||
Box::pin(async {})
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unreachable_code)]
|
||||
impl ErrorHandlerExt<Infallible> for IgnoringErrorHandlerSafe {
|
||||
fn handle_error_with_deps(
|
||||
fn handle_error(
|
||||
self: Arc<Self>,
|
||||
_deps: DependencyMap,
|
||||
_: Infallible,
|
||||
_: Option<DependencyMap>,
|
||||
) -> BoxFuture<'static, ()> {
|
||||
Box::pin(async {})
|
||||
}
|
||||
|
@ -220,9 +187,9 @@ impl ErrorHandlerExt<Infallible> for IgnoringErrorHandlerSafe {
|
|||
/// # async fn main_() {
|
||||
/// use teloxide::error_handlers::{ErrorHandler, LoggingErrorHandler};
|
||||
///
|
||||
/// LoggingErrorHandler::new().handle_error(()).await;
|
||||
/// LoggingErrorHandler::with_custom_text("Omg1").handle_error(404).await;
|
||||
/// LoggingErrorHandler::with_custom_text("Omg2").handle_error("Invalid data type!").await;
|
||||
/// 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;
|
||||
/// # }
|
||||
/// ```
|
||||
pub struct LoggingErrorHandler {
|
||||
|
@ -253,21 +220,7 @@ impl<E> ErrorHandler<E> for LoggingErrorHandler
|
|||
where
|
||||
E: Debug,
|
||||
{
|
||||
fn handle_error(self: Arc<Self>, error: E) -> BoxFuture<'static, ()> {
|
||||
log::error!("{text}: {:?}", error, text = self.text);
|
||||
Box::pin(async {})
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> ErrorHandlerExt<E> for LoggingErrorHandler
|
||||
where
|
||||
E: Debug,
|
||||
{
|
||||
fn handle_error_with_deps(
|
||||
self: Arc<Self>,
|
||||
_deps: DependencyMap,
|
||||
error: E,
|
||||
) -> BoxFuture<'static, ()> {
|
||||
fn handle_error(self: Arc<Self>, error: E, _: Option<DependencyMap>) -> BoxFuture<'static, ()> {
|
||||
log::error!("{text}: {:?}", error, text = self.text);
|
||||
Box::pin(async {})
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue