mirror of
https://github.com/teloxide/teloxide.git
synced 2024-12-23 06:51:01 +01:00
Merge pull request #705 from teloxide/update_listener_type_err
Turn `UpdateListener`'s generic error into an associated type
This commit is contained in:
commit
014075573d
9 changed files with 55 additions and 40 deletions
|
@ -6,6 +6,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
## unreleased
|
## unreleased
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- `UpdateListener` now has an associated type `Err` instead of a generic
|
||||||
|
- `AsUpdateStream` now has an associated type `StreamErr` instead of a generic
|
||||||
|
|
||||||
## 0.10.1 - 2022-07-22
|
## 0.10.1 - 2022-07-22
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
|
@ -287,14 +287,14 @@ where
|
||||||
/// This method adds the same dependencies as [`Dispatcher::dispatch`].
|
/// This method adds the same dependencies as [`Dispatcher::dispatch`].
|
||||||
///
|
///
|
||||||
/// [`shutdown`]: ShutdownToken::shutdown
|
/// [`shutdown`]: ShutdownToken::shutdown
|
||||||
pub async fn dispatch_with_listener<'a, UListener, ListenerE, Eh>(
|
pub async fn dispatch_with_listener<'a, UListener, Eh>(
|
||||||
&'a mut self,
|
&'a mut self,
|
||||||
mut update_listener: UListener,
|
mut update_listener: UListener,
|
||||||
update_listener_error_handler: Arc<Eh>,
|
update_listener_error_handler: Arc<Eh>,
|
||||||
) where
|
) where
|
||||||
UListener: UpdateListener<ListenerE> + 'a,
|
UListener: UpdateListener + 'a,
|
||||||
Eh: ErrorHandler<ListenerE> + 'a,
|
Eh: ErrorHandler<UListener::Err> + 'a,
|
||||||
ListenerE: Debug,
|
UListener::Err: Debug,
|
||||||
{
|
{
|
||||||
// FIXME: there should be a way to check if dependency is already inserted
|
// FIXME: there should be a way to check if dependency is already inserted
|
||||||
let me = self.bot.get_me().send().await.expect("Failed to retrieve 'me'");
|
let me = self.bot.get_me().send().await.expect("Failed to retrieve 'me'");
|
||||||
|
|
|
@ -78,7 +78,7 @@ where
|
||||||
/// [`commands_repl`]: crate::dispatching::repls::commands_repl()
|
/// [`commands_repl`]: crate::dispatching::repls::commands_repl()
|
||||||
/// [`UpdateListener`]: crate::dispatching::update_listeners::UpdateListener
|
/// [`UpdateListener`]: crate::dispatching::update_listeners::UpdateListener
|
||||||
#[cfg(feature = "ctrlc_handler")]
|
#[cfg(feature = "ctrlc_handler")]
|
||||||
pub async fn commands_repl_with_listener<'a, R, Cmd, H, L, ListenerE, E, Args>(
|
pub async fn commands_repl_with_listener<'a, R, Cmd, H, L, E, Args>(
|
||||||
bot: R,
|
bot: R,
|
||||||
handler: H,
|
handler: H,
|
||||||
listener: L,
|
listener: L,
|
||||||
|
@ -86,8 +86,8 @@ pub async fn commands_repl_with_listener<'a, R, Cmd, H, L, ListenerE, E, Args>(
|
||||||
) where
|
) where
|
||||||
Cmd: BotCommands + Send + Sync + 'static,
|
Cmd: BotCommands + Send + Sync + 'static,
|
||||||
H: Injectable<DependencyMap, Result<(), E>, Args> + Send + Sync + 'static,
|
H: Injectable<DependencyMap, Result<(), E>, Args> + Send + Sync + 'static,
|
||||||
L: UpdateListener<ListenerE> + Send + 'a,
|
L: UpdateListener + Send + 'a,
|
||||||
ListenerE: Debug + Send + 'a,
|
L::Err: Debug + Send + 'a,
|
||||||
R: Requester + Clone + Send + Sync + 'static,
|
R: Requester + Clone + Send + Sync + 'static,
|
||||||
E: Debug + Send + Sync + 'static,
|
E: Debug + Send + Sync + 'static,
|
||||||
{
|
{
|
||||||
|
|
|
@ -60,11 +60,11 @@ where
|
||||||
/// [`repl`]: crate::dispatching::repls::repl()
|
/// [`repl`]: crate::dispatching::repls::repl()
|
||||||
/// [`UpdateListener`]: crate::dispatching::update_listeners::UpdateListener
|
/// [`UpdateListener`]: crate::dispatching::update_listeners::UpdateListener
|
||||||
#[cfg(feature = "ctrlc_handler")]
|
#[cfg(feature = "ctrlc_handler")]
|
||||||
pub async fn repl_with_listener<'a, R, H, E, L, ListenerE, Args>(bot: R, handler: H, listener: L)
|
pub async fn repl_with_listener<'a, R, H, E, L, Args>(bot: R, handler: H, listener: L)
|
||||||
where
|
where
|
||||||
H: Injectable<DependencyMap, Result<(), E>, Args> + Send + Sync + 'static,
|
H: Injectable<DependencyMap, Result<(), E>, Args> + Send + Sync + 'static,
|
||||||
L: UpdateListener<ListenerE> + Send + 'a,
|
L: UpdateListener + Send + 'a,
|
||||||
ListenerE: Debug,
|
L::Err: Debug,
|
||||||
Result<(), E>: OnError<E>,
|
Result<(), E>: OnError<E>,
|
||||||
E: Debug + Send + Sync + 'static,
|
E: Debug + Send + Sync + 'static,
|
||||||
R: Requester + Clone + Send + Sync + 'static,
|
R: Requester + Clone + Send + Sync + 'static,
|
||||||
|
|
|
@ -59,7 +59,12 @@ pub use self::{
|
||||||
/// - [`AsUpdateStream::as_stream`]
|
/// - [`AsUpdateStream::as_stream`]
|
||||||
///
|
///
|
||||||
/// [module-level documentation]: mod@self
|
/// [module-level documentation]: mod@self
|
||||||
pub trait UpdateListener<E>: for<'a> AsUpdateStream<'a, E> {
|
pub trait UpdateListener:
|
||||||
|
for<'a> AsUpdateStream<'a, StreamErr = <Self as UpdateListener>::Err>
|
||||||
|
{
|
||||||
|
/// The type of errors that can be returned from this listener.
|
||||||
|
type Err;
|
||||||
|
|
||||||
/// The type of token which allows to stop this listener.
|
/// The type of token which allows to stop this listener.
|
||||||
type StopToken: StopToken + Send;
|
type StopToken: StopToken + Send;
|
||||||
|
|
||||||
|
@ -110,16 +115,19 @@ pub trait UpdateListener<E>: for<'a> AsUpdateStream<'a, E> {
|
||||||
/// [`UpdateListener`]'s supertrait/extension.
|
/// [`UpdateListener`]'s supertrait/extension.
|
||||||
///
|
///
|
||||||
/// This trait is a workaround to not require GAT.
|
/// This trait is a workaround to not require GAT.
|
||||||
pub trait AsUpdateStream<'a, E> {
|
pub trait AsUpdateStream<'a> {
|
||||||
|
/// Error that can be returned from the [`Stream`]
|
||||||
|
///
|
||||||
|
/// [`Stream`]: AsUpdateStream::Stream
|
||||||
|
// NB: This should be named differently to `UpdateListener::Err`, so that it's
|
||||||
|
// unambiguous
|
||||||
|
type StreamErr;
|
||||||
|
|
||||||
/// The stream of updates from Telegram.
|
/// The stream of updates from Telegram.
|
||||||
// HACK: There is currently no way to write something like
|
// NB: `Send` is not strictly required here, but it makes it easier to return
|
||||||
// `-> impl for<'a> AsUpdateStream<'a, E, Stream: Send>`. Since we return
|
// `impl AsUpdateStream` and also you want `Send` streams almost (?) always
|
||||||
// `impl UpdateListener<E>` from `polling`, we need to have `Send` bound here,
|
// anyway.
|
||||||
// to make the stream `Send`.
|
type Stream: Stream<Item = Result<Update, Self::StreamErr>> + Send + 'a;
|
||||||
//
|
|
||||||
// Without this it's, for example, impossible to spawn a tokio task with
|
|
||||||
// teloxide polling.
|
|
||||||
type Stream: Stream<Item = Result<Update, E>> + Send + 'a;
|
|
||||||
|
|
||||||
/// Creates the update [`Stream`].
|
/// Creates the update [`Stream`].
|
||||||
///
|
///
|
||||||
|
@ -128,9 +136,9 @@ pub trait AsUpdateStream<'a, E> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn assert_update_listener<L, E>(listener: L) -> L
|
pub(crate) fn assert_update_listener<L>(listener: L) -> L
|
||||||
where
|
where
|
||||||
L: UpdateListener<E>,
|
L: UpdateListener,
|
||||||
{
|
{
|
||||||
listener
|
listener
|
||||||
}
|
}
|
||||||
|
|
|
@ -291,7 +291,8 @@ pub struct PollingStream<'a, B: Requester> {
|
||||||
in_flight: Option<<B::GetUpdates as Request>::Send>,
|
in_flight: Option<<B::GetUpdates as Request>::Send>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<B: Requester + Send + 'static> UpdateListener<B::Err> for Polling<B> {
|
impl<B: Requester + Send + 'static> UpdateListener for Polling<B> {
|
||||||
|
type Err = B::Err;
|
||||||
type StopToken = AsyncStopToken;
|
type StopToken = AsyncStopToken;
|
||||||
|
|
||||||
fn stop_token(&mut self) -> Self::StopToken {
|
fn stop_token(&mut self) -> Self::StopToken {
|
||||||
|
@ -309,7 +310,8 @@ impl<B: Requester + Send + 'static> UpdateListener<B::Err> for Polling<B> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, B: Requester + Send + 'a> AsUpdateStream<'a, B::Err> for Polling<B> {
|
impl<'a, B: Requester + Send + 'a> AsUpdateStream<'a> for Polling<B> {
|
||||||
|
type StreamErr = B::Err;
|
||||||
type Stream = PollingStream<'a, B>;
|
type Stream = PollingStream<'a, B>;
|
||||||
|
|
||||||
fn as_stream(&'a mut self) -> Self::Stream {
|
fn as_stream(&'a mut self) -> Self::Stream {
|
||||||
|
|
|
@ -5,7 +5,7 @@ use futures::Stream;
|
||||||
use crate::{
|
use crate::{
|
||||||
dispatching::{
|
dispatching::{
|
||||||
stop_token::{self, StopToken},
|
stop_token::{self, StopToken},
|
||||||
update_listeners::{AsUpdateStream, UpdateListener},
|
update_listeners::{assert_update_listener, AsUpdateStream, UpdateListener},
|
||||||
},
|
},
|
||||||
types::{AllowedUpdate, Update},
|
types::{AllowedUpdate, Update},
|
||||||
};
|
};
|
||||||
|
@ -103,7 +103,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, St, Assf, Sf, Hauf, Thf, Strm, E> AsUpdateStream<'a, E>
|
impl<'a, St, Assf, Sf, Hauf, Thf, Strm, E> AsUpdateStream<'a>
|
||||||
for StatefulListener<St, Assf, Hauf, Sf, Thf>
|
for StatefulListener<St, Assf, Hauf, Sf, Thf>
|
||||||
where
|
where
|
||||||
(St, Strm): 'a,
|
(St, Strm): 'a,
|
||||||
|
@ -111,6 +111,7 @@ where
|
||||||
Assf: FnMut(&'a mut St) -> Strm,
|
Assf: FnMut(&'a mut St) -> Strm,
|
||||||
Strm: Stream<Item = Result<Update, E>>,
|
Strm: Stream<Item = Result<Update, E>>,
|
||||||
{
|
{
|
||||||
|
type StreamErr = E;
|
||||||
type Stream = Strm;
|
type Stream = Strm;
|
||||||
|
|
||||||
fn as_stream(&'a mut self) -> Self::Stream {
|
fn as_stream(&'a mut self) -> Self::Stream {
|
||||||
|
@ -118,15 +119,15 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<St, Assf, Sf, Hauf, Stt, Thf, E> UpdateListener<E>
|
impl<St, Assf, Sf, Hauf, Stt, Thf, E> UpdateListener for StatefulListener<St, Assf, Sf, Hauf, Thf>
|
||||||
for StatefulListener<St, Assf, Sf, Hauf, Thf>
|
|
||||||
where
|
where
|
||||||
Self: for<'a> AsUpdateStream<'a, E>,
|
Self: for<'a> AsUpdateStream<'a, StreamErr = E>,
|
||||||
Sf: FnMut(&mut St) -> Stt,
|
Sf: FnMut(&mut St) -> Stt,
|
||||||
Stt: StopToken + Send,
|
Stt: StopToken + Send,
|
||||||
Hauf: FnMut(&mut St, &mut dyn Iterator<Item = AllowedUpdate>),
|
Hauf: FnMut(&mut St, &mut dyn Iterator<Item = AllowedUpdate>),
|
||||||
Thf: Fn(&St) -> Option<Duration>,
|
Thf: Fn(&St) -> Option<Duration>,
|
||||||
{
|
{
|
||||||
|
type Err = E;
|
||||||
type StopToken = Stt;
|
type StopToken = Stt;
|
||||||
|
|
||||||
fn stop_token(&mut self) -> Stt {
|
fn stop_token(&mut self) -> Stt {
|
||||||
|
@ -143,10 +144,3 @@ where
|
||||||
self.timeout_hint.as_ref().and_then(|f| f(&self.state))
|
self.timeout_hint.as_ref().and_then(|f| f(&self.state))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assert_update_listener<L, E>(l: L) -> L
|
|
||||||
where
|
|
||||||
L: UpdateListener<E>,
|
|
||||||
{
|
|
||||||
l
|
|
||||||
}
|
|
||||||
|
|
|
@ -38,7 +38,10 @@ use crate::{
|
||||||
///
|
///
|
||||||
/// [`axum_to_router`] and [`axum_no_setup`] for lower-level versions of this
|
/// [`axum_to_router`] and [`axum_no_setup`] for lower-level versions of this
|
||||||
/// function.
|
/// function.
|
||||||
pub async fn axum<R>(bot: R, options: Options) -> Result<impl UpdateListener<Infallible>, R::Err>
|
pub async fn axum<R>(
|
||||||
|
bot: R,
|
||||||
|
options: Options,
|
||||||
|
) -> Result<impl UpdateListener<Err = Infallible>, R::Err>
|
||||||
where
|
where
|
||||||
R: Requester + Send + 'static,
|
R: Requester + Send + 'static,
|
||||||
<R as Requester>::DeleteWebhook: Send,
|
<R as Requester>::DeleteWebhook: Send,
|
||||||
|
@ -107,7 +110,10 @@ where
|
||||||
pub async fn axum_to_router<R>(
|
pub async fn axum_to_router<R>(
|
||||||
bot: R,
|
bot: R,
|
||||||
mut options: Options,
|
mut options: Options,
|
||||||
) -> Result<(impl UpdateListener<Infallible>, impl Future<Output = ()> + Send, axum::Router), R::Err>
|
) -> Result<
|
||||||
|
(impl UpdateListener<Err = Infallible>, impl Future<Output = ()> + Send, axum::Router),
|
||||||
|
R::Err,
|
||||||
|
>
|
||||||
where
|
where
|
||||||
R: Requester + Send,
|
R: Requester + Send,
|
||||||
<R as Requester>::DeleteWebhook: Send,
|
<R as Requester>::DeleteWebhook: Send,
|
||||||
|
@ -148,7 +154,7 @@ where
|
||||||
/// function.
|
/// function.
|
||||||
pub fn axum_no_setup(
|
pub fn axum_no_setup(
|
||||||
options: Options,
|
options: Options,
|
||||||
) -> (impl UpdateListener<Infallible>, impl Future<Output = ()>, axum::Router) {
|
) -> (impl UpdateListener<Err = Infallible>, impl Future<Output = ()>, axum::Router) {
|
||||||
use crate::{
|
use crate::{
|
||||||
dispatching::{
|
dispatching::{
|
||||||
stop_token::AsyncStopToken,
|
stop_token::AsyncStopToken,
|
||||||
|
|
|
@ -93,7 +93,7 @@ impl fmt::Display for IdleShutdownError {
|
||||||
|
|
||||||
impl std::error::Error for IdleShutdownError {}
|
impl std::error::Error for IdleShutdownError {}
|
||||||
|
|
||||||
pub(crate) fn shutdown_check_timeout_for<E>(update_listener: &impl UpdateListener<E>) -> Duration {
|
pub(crate) fn shutdown_check_timeout_for(update_listener: &impl UpdateListener) -> Duration {
|
||||||
const MIN_SHUTDOWN_CHECK_TIMEOUT: Duration = Duration::from_secs(1);
|
const MIN_SHUTDOWN_CHECK_TIMEOUT: Duration = Duration::from_secs(1);
|
||||||
const DZERO: Duration = Duration::ZERO;
|
const DZERO: Duration = Duration::ZERO;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue