mirror of
https://github.com/teloxide/teloxide.git
synced 2025-01-03 17:52:12 +01:00
Fix error handlers
This commit is contained in:
parent
d23b226e86
commit
f20932a730
6 changed files with 159 additions and 162 deletions
|
@ -47,25 +47,25 @@ where
|
|||
///
|
||||
/// [`InMemStorage`]: crate::dispatching::dialogue::InMemStorage
|
||||
#[must_use]
|
||||
pub fn new(handler: H) -> Arc<Self> {
|
||||
Arc::new(Self {
|
||||
pub fn new(handler: H) -> Self {
|
||||
Self {
|
||||
storage: InMemStorage::new(),
|
||||
handler: Arc::new(handler),
|
||||
senders: Arc::new(Map::new()),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a dispatcher with the specified `handler` and `storage`.
|
||||
#[must_use]
|
||||
pub fn with_storage<Stg>(handler: H, storage: Arc<Stg>) -> Arc<Self>
|
||||
pub fn with_storage<Stg>(handler: H, storage: Arc<Stg>) -> Self
|
||||
where
|
||||
Stg: Storage<D> + Send + Sync + 'static,
|
||||
{
|
||||
Arc::new(Self {
|
||||
Self {
|
||||
storage,
|
||||
handler: Arc::new(handler),
|
||||
senders: Arc::new(Map::new()),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use std::pin::Pin;
|
||||
|
||||
use crate::prelude::{DialogueDispatcherHandlerCtx, DialogueStage};
|
||||
use futures::future::BoxFuture;
|
||||
use std::{future::Future, sync::Arc};
|
||||
|
||||
/// An asynchronous handler of an update used in [`DialogueDispatcher`].
|
||||
|
@ -14,7 +13,7 @@ pub trait DialogueDispatcherHandler<Upd, D> {
|
|||
fn handle(
|
||||
self: Arc<Self>,
|
||||
ctx: DialogueDispatcherHandlerCtx<Upd, D>,
|
||||
) -> Pin<Box<dyn Future<Output = DialogueStage<D>> + Send + 'static>>
|
||||
) -> BoxFuture<'static, DialogueStage<D>>
|
||||
where
|
||||
DialogueDispatcherHandlerCtx<Upd, D>: Send + 'static;
|
||||
}
|
||||
|
@ -27,7 +26,7 @@ where
|
|||
fn handle(
|
||||
self: Arc<Self>,
|
||||
ctx: DialogueDispatcherHandlerCtx<Upd, D>,
|
||||
) -> Pin<Box<dyn Future<Output = Fut::Output> + Send + 'static>>
|
||||
) -> BoxFuture<'static, Fut::Output>
|
||||
where
|
||||
DialogueDispatcherHandlerCtx<Upd, D>: Send + 'static,
|
||||
{
|
||||
|
|
|
@ -211,7 +211,7 @@ impl Dispatcher {
|
|||
pub async fn dispatch(&self) {
|
||||
self.dispatch_with_listener(
|
||||
update_listeners::polling_default(Arc::clone(&self.bot)),
|
||||
&LoggingErrorHandler::new("An error from the update listener"),
|
||||
LoggingErrorHandler::new("An error from the update listener"),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
@ -221,7 +221,7 @@ impl Dispatcher {
|
|||
pub async fn dispatch_with_listener<'a, UListener, ListenerE, Eh>(
|
||||
&'a self,
|
||||
update_listener: UListener,
|
||||
update_listener_error_handler: &'a Eh,
|
||||
update_listener_error_handler: Arc<Eh>,
|
||||
) where
|
||||
UListener: UpdateListener<ListenerE> + 'a,
|
||||
Eh: ErrorHandler<ListenerE> + 'a,
|
||||
|
@ -230,105 +230,112 @@ impl Dispatcher {
|
|||
let update_listener = Box::pin(update_listener);
|
||||
|
||||
update_listener
|
||||
.for_each(move |update| async move {
|
||||
log::trace!("Dispatcher received an update: {:?}", update);
|
||||
.for_each(move |update| {
|
||||
let update_listener_error_handler =
|
||||
Arc::clone(&update_listener_error_handler);
|
||||
|
||||
let update = match update {
|
||||
Ok(update) => update,
|
||||
Err(error) => {
|
||||
update_listener_error_handler.handle_error(error).await;
|
||||
return;
|
||||
}
|
||||
};
|
||||
async move {
|
||||
log::trace!("Dispatcher received an update: {:?}", update);
|
||||
|
||||
match update.kind {
|
||||
UpdateKind::Message(message) => {
|
||||
send!(
|
||||
&self.bot,
|
||||
&self.messages_queue,
|
||||
message,
|
||||
UpdateKind::Message
|
||||
);
|
||||
}
|
||||
UpdateKind::EditedMessage(message) => {
|
||||
send!(
|
||||
&self.bot,
|
||||
&self.edited_messages_queue,
|
||||
message,
|
||||
UpdateKind::EditedMessage
|
||||
);
|
||||
}
|
||||
UpdateKind::ChannelPost(post) => {
|
||||
send!(
|
||||
&self.bot,
|
||||
&self.channel_posts_queue,
|
||||
post,
|
||||
UpdateKind::ChannelPost
|
||||
);
|
||||
}
|
||||
UpdateKind::EditedChannelPost(post) => {
|
||||
send!(
|
||||
&self.bot,
|
||||
&self.edited_channel_posts_queue,
|
||||
post,
|
||||
UpdateKind::EditedChannelPost
|
||||
);
|
||||
}
|
||||
UpdateKind::InlineQuery(query) => {
|
||||
send!(
|
||||
&self.bot,
|
||||
&self.inline_queries_queue,
|
||||
query,
|
||||
UpdateKind::InlineQuery
|
||||
);
|
||||
}
|
||||
UpdateKind::ChosenInlineResult(result) => {
|
||||
send!(
|
||||
&self.bot,
|
||||
&self.chosen_inline_results_queue,
|
||||
result,
|
||||
UpdateKind::ChosenInlineResult
|
||||
);
|
||||
}
|
||||
UpdateKind::CallbackQuery(query) => {
|
||||
send!(
|
||||
&self.bot,
|
||||
&self.callback_queries_queue,
|
||||
query,
|
||||
UpdateKind::CallbackQuer
|
||||
);
|
||||
}
|
||||
UpdateKind::ShippingQuery(query) => {
|
||||
send!(
|
||||
&self.bot,
|
||||
&self.shipping_queries_queue,
|
||||
query,
|
||||
UpdateKind::ShippingQuery
|
||||
);
|
||||
}
|
||||
UpdateKind::PreCheckoutQuery(query) => {
|
||||
send!(
|
||||
&self.bot,
|
||||
&self.pre_checkout_queries_queue,
|
||||
query,
|
||||
UpdateKind::PreCheckoutQuery
|
||||
);
|
||||
}
|
||||
UpdateKind::Poll(poll) => {
|
||||
send!(
|
||||
&self.bot,
|
||||
&self.polls_queue,
|
||||
poll,
|
||||
UpdateKind::Poll
|
||||
);
|
||||
}
|
||||
UpdateKind::PollAnswer(answer) => {
|
||||
send!(
|
||||
&self.bot,
|
||||
&self.poll_answers_queue,
|
||||
answer,
|
||||
UpdateKind::PollAnswer
|
||||
);
|
||||
let update = match update {
|
||||
Ok(update) => update,
|
||||
Err(error) => {
|
||||
Arc::clone(&update_listener_error_handler)
|
||||
.handle_error(error)
|
||||
.await;
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
match update.kind {
|
||||
UpdateKind::Message(message) => {
|
||||
send!(
|
||||
&self.bot,
|
||||
&self.messages_queue,
|
||||
message,
|
||||
UpdateKind::Message
|
||||
);
|
||||
}
|
||||
UpdateKind::EditedMessage(message) => {
|
||||
send!(
|
||||
&self.bot,
|
||||
&self.edited_messages_queue,
|
||||
message,
|
||||
UpdateKind::EditedMessage
|
||||
);
|
||||
}
|
||||
UpdateKind::ChannelPost(post) => {
|
||||
send!(
|
||||
&self.bot,
|
||||
&self.channel_posts_queue,
|
||||
post,
|
||||
UpdateKind::ChannelPost
|
||||
);
|
||||
}
|
||||
UpdateKind::EditedChannelPost(post) => {
|
||||
send!(
|
||||
&self.bot,
|
||||
&self.edited_channel_posts_queue,
|
||||
post,
|
||||
UpdateKind::EditedChannelPost
|
||||
);
|
||||
}
|
||||
UpdateKind::InlineQuery(query) => {
|
||||
send!(
|
||||
&self.bot,
|
||||
&self.inline_queries_queue,
|
||||
query,
|
||||
UpdateKind::InlineQuery
|
||||
);
|
||||
}
|
||||
UpdateKind::ChosenInlineResult(result) => {
|
||||
send!(
|
||||
&self.bot,
|
||||
&self.chosen_inline_results_queue,
|
||||
result,
|
||||
UpdateKind::ChosenInlineResult
|
||||
);
|
||||
}
|
||||
UpdateKind::CallbackQuery(query) => {
|
||||
send!(
|
||||
&self.bot,
|
||||
&self.callback_queries_queue,
|
||||
query,
|
||||
UpdateKind::CallbackQuer
|
||||
);
|
||||
}
|
||||
UpdateKind::ShippingQuery(query) => {
|
||||
send!(
|
||||
&self.bot,
|
||||
&self.shipping_queries_queue,
|
||||
query,
|
||||
UpdateKind::ShippingQuery
|
||||
);
|
||||
}
|
||||
UpdateKind::PreCheckoutQuery(query) => {
|
||||
send!(
|
||||
&self.bot,
|
||||
&self.pre_checkout_queries_queue,
|
||||
query,
|
||||
UpdateKind::PreCheckoutQuery
|
||||
);
|
||||
}
|
||||
UpdateKind::Poll(poll) => {
|
||||
send!(
|
||||
&self.bot,
|
||||
&self.polls_queue,
|
||||
poll,
|
||||
UpdateKind::Poll
|
||||
);
|
||||
}
|
||||
UpdateKind::PollAnswer(answer) => {
|
||||
send!(
|
||||
&self.bot,
|
||||
&self.poll_answers_queue,
|
||||
answer,
|
||||
UpdateKind::PollAnswer
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use std::{future::Future, pin::Pin};
|
||||
use std::future::Future;
|
||||
|
||||
use crate::dispatching::{DispatcherHandlerCtx, DispatcherHandlerRx};
|
||||
use futures::future::BoxFuture;
|
||||
|
||||
/// An asynchronous handler of a stream of updates used in [`Dispatcher`].
|
||||
///
|
||||
|
@ -13,7 +14,7 @@ pub trait DispatcherHandler<Upd> {
|
|||
fn handle(
|
||||
self,
|
||||
updates: DispatcherHandlerRx<Upd>,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'static>>
|
||||
) -> BoxFuture<'static, ()>
|
||||
where
|
||||
DispatcherHandlerCtx<Upd>: Send + 'static;
|
||||
}
|
||||
|
@ -23,10 +24,7 @@ where
|
|||
F: FnOnce(DispatcherHandlerRx<Upd>) -> Fut + Send + 'static,
|
||||
Fut: Future<Output = ()> + Send + 'static,
|
||||
{
|
||||
fn handle(
|
||||
self,
|
||||
updates: DispatcherHandlerRx<Upd>,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + Send + 'static>>
|
||||
fn handle(self, updates: DispatcherHandlerRx<Upd>) -> BoxFuture<'static, ()>
|
||||
where
|
||||
DispatcherHandlerCtx<Upd>: Send + 'static,
|
||||
{
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use std::{convert::Infallible, fmt::Debug, future::Future, pin::Pin};
|
||||
use futures::future::BoxFuture;
|
||||
use std::{convert::Infallible, fmt::Debug, future::Future, sync::Arc};
|
||||
|
||||
/// An asynchronous handler of an error.
|
||||
///
|
||||
|
@ -6,26 +7,16 @@ use std::{convert::Infallible, fmt::Debug, future::Future, pin::Pin};
|
|||
/// overview](crate::dispatching).
|
||||
pub trait ErrorHandler<E> {
|
||||
#[must_use]
|
||||
fn handle_error<'a>(
|
||||
&'a self,
|
||||
error: E,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + 'a>>
|
||||
where
|
||||
E: 'a;
|
||||
fn handle_error(self: Arc<Self>, error: E) -> BoxFuture<'static, ()>;
|
||||
}
|
||||
|
||||
impl<E, F, Fut> ErrorHandler<E> for F
|
||||
where
|
||||
F: Fn(E) -> Fut,
|
||||
Fut: Future<Output = ()>,
|
||||
F: Fn(E) -> Fut + Send + Sync + 'static,
|
||||
E: Send + 'static,
|
||||
Fut: Future<Output = ()> + Send,
|
||||
{
|
||||
fn handle_error<'a>(
|
||||
&'a self,
|
||||
error: E,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + 'a>>
|
||||
where
|
||||
E: 'a,
|
||||
{
|
||||
fn handle_error(self: Arc<Self>, error: E) -> BoxFuture<'static, ()> {
|
||||
Box::pin(async move { self(error).await })
|
||||
}
|
||||
}
|
||||
|
@ -38,21 +29,22 @@ where
|
|||
/// # async fn main_() {
|
||||
/// use teloxide::dispatching::{ErrorHandler, IgnoringErrorHandler};
|
||||
///
|
||||
/// IgnoringErrorHandler.handle_error(()).await;
|
||||
/// IgnoringErrorHandler.handle_error(404).await;
|
||||
/// IgnoringErrorHandler.handle_error("error").await;
|
||||
/// IgnoringErrorHandler::new().handle_error(()).await;
|
||||
/// IgnoringErrorHandler::new().handle_error(404).await;
|
||||
/// IgnoringErrorHandler::new().handle_error("error").await;
|
||||
/// # }
|
||||
/// ```
|
||||
pub struct IgnoringErrorHandler;
|
||||
|
||||
impl IgnoringErrorHandler {
|
||||
#[must_use]
|
||||
pub fn new() -> Arc<Self> {
|
||||
Arc::new(Self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E> ErrorHandler<E> for IgnoringErrorHandler {
|
||||
fn handle_error<'a>(
|
||||
&'a self,
|
||||
_: E,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + 'a>>
|
||||
where
|
||||
E: 'a,
|
||||
{
|
||||
fn handle_error(self: Arc<Self>, _: E) -> BoxFuture<'static, ()> {
|
||||
Box::pin(async {})
|
||||
}
|
||||
}
|
||||
|
@ -71,10 +63,10 @@ impl<E> ErrorHandler<E> for IgnoringErrorHandler {
|
|||
/// let result: Result<String, Infallible> = "str".try_into();
|
||||
/// match result {
|
||||
/// Ok(string) => println!("{}", string),
|
||||
/// Err(inf) => IgnoringErrorHandlerSafe.handle_error(inf).await,
|
||||
/// Err(inf) => IgnoringErrorHandlerSafe::new().handle_error(inf).await,
|
||||
/// }
|
||||
///
|
||||
/// IgnoringErrorHandlerSafe.handle_error(return).await; // return type of `return` is `!` (aka never)
|
||||
/// IgnoringErrorHandlerSafe::new().handle_error(return).await; // return type of `return` is `!` (aka never)
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
|
@ -88,15 +80,16 @@ impl<E> ErrorHandler<E> for IgnoringErrorHandler {
|
|||
/// [`Infallible`]: std::convert::Infallible
|
||||
pub struct IgnoringErrorHandlerSafe;
|
||||
|
||||
impl IgnoringErrorHandlerSafe {
|
||||
#[must_use]
|
||||
pub fn new() -> Arc<Self> {
|
||||
Arc::new(Self)
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unreachable_code)]
|
||||
impl ErrorHandler<Infallible> for IgnoringErrorHandlerSafe {
|
||||
fn handle_error<'a>(
|
||||
&'a self,
|
||||
_: Infallible,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + 'a>>
|
||||
where
|
||||
Infallible: 'a,
|
||||
{
|
||||
fn handle_error(self: Arc<Self>, _: Infallible) -> BoxFuture<'static, ()> {
|
||||
Box::pin(async {})
|
||||
}
|
||||
}
|
||||
|
@ -109,14 +102,13 @@ impl ErrorHandler<Infallible> for IgnoringErrorHandlerSafe {
|
|||
/// # async fn main_() {
|
||||
/// use teloxide::dispatching::{ErrorHandler, LoggingErrorHandler};
|
||||
///
|
||||
/// LoggingErrorHandler::default().handle_error(()).await;
|
||||
/// LoggingErrorHandler::empty().handle_error(()).await;
|
||||
/// LoggingErrorHandler::new("error").handle_error(404).await;
|
||||
/// LoggingErrorHandler::new("error")
|
||||
/// .handle_error("Invalid data type!")
|
||||
/// .await;
|
||||
/// # }
|
||||
/// ```
|
||||
#[derive(Default)]
|
||||
pub struct LoggingErrorHandler {
|
||||
text: String,
|
||||
}
|
||||
|
@ -126,11 +118,17 @@ impl LoggingErrorHandler {
|
|||
///
|
||||
/// The logs will be printed in this format: `{text}: {:?}`.
|
||||
#[must_use]
|
||||
pub fn new<T>(text: T) -> Self
|
||||
pub fn new<T>(text: T) -> Arc<Self>
|
||||
where
|
||||
T: Into<String>,
|
||||
{
|
||||
Self { text: text.into() }
|
||||
Arc::new(Self { text: text.into() })
|
||||
}
|
||||
|
||||
/// A shortcut for `LoggingErrorHandler::new("Error".to_owned())`.
|
||||
#[must_use]
|
||||
pub fn empty() -> Arc<Self> {
|
||||
Self::new("Error".to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -138,13 +136,7 @@ impl<E> ErrorHandler<E> for LoggingErrorHandler
|
|||
where
|
||||
E: Debug,
|
||||
{
|
||||
fn handle_error<'a>(
|
||||
&'a self,
|
||||
error: E,
|
||||
) -> Pin<Box<dyn Future<Output = ()> + 'a>>
|
||||
where
|
||||
E: 'a,
|
||||
{
|
||||
fn handle_error(self: Arc<Self>, error: E) -> BoxFuture<'static, ()> {
|
||||
log::error!("{text}: {:?}", error, text = self.text);
|
||||
Box::pin(async {})
|
||||
}
|
||||
|
|
|
@ -6,7 +6,8 @@ pub use crate::{
|
|||
exit, next, DialogueDispatcher, DialogueDispatcherHandlerCtx,
|
||||
DialogueStage, GetChatId,
|
||||
},
|
||||
Dispatcher, DispatcherHandlerCtx, DispatcherHandlerRx, LoggingErrorHandler, ErrorHandler
|
||||
Dispatcher, DispatcherHandlerCtx, DispatcherHandlerRx, ErrorHandler,
|
||||
LoggingErrorHandler,
|
||||
},
|
||||
requests::{Request, ResponseResult},
|
||||
types::{Message, Update},
|
||||
|
|
Loading…
Reference in a new issue