teloxide_core/adaptors/throttle/
settings.rs

1use std::pin::Pin;
2
3use futures::{future::ready, Future};
4
5// Required to not trigger `clippy::type-complexity` lint
6type BoxedFnMut<I, O> = Box<dyn FnMut(I) -> O + Send>;
7type BoxedFuture = Pin<Box<dyn Future<Output = ()> + Send>>;
8
9/// Settings used by [`Throttle`] adaptor.
10///
11/// ## Examples
12///
13/// ```
14/// use teloxide_core::adaptors::throttle;
15///
16/// let settings = throttle::Settings::default()
17///     .on_queue_full(|pending| async move { /* do something when internal queue is full */ });
18///
19/// // use settings in `Throttle::with_settings` or other constructors
20/// # let _ = settings;
21/// ```
22///
23/// [`Throttle`]: crate::adaptors::throttle::Throttle
24#[must_use]
25#[non_exhaustive]
26pub struct Settings {
27    pub limits: Limits,
28    pub on_queue_full: BoxedFnMut<usize, BoxedFuture>,
29    pub retry: bool,
30    pub check_slow_mode: bool,
31}
32
33/// Telegram request limits.
34///
35/// This struct is used in [`Throttle`].
36///
37/// Note that you may ask telegram [@BotSupport] to increase limits for your
38/// particular bot if it has a lot of users (but they may or may not do that).
39///
40/// [@BotSupport]: https://t.me/botsupport
41/// [`Throttle`]: crate::adaptors::throttle::Throttle
42#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
43pub struct Limits {
44    /// Allowed messages in one chat per second.
45    pub messages_per_sec_chat: u32,
46
47    /// Allowed messages in one chat per minute.
48    pub messages_per_min_chat: u32,
49
50    /// Allowed messages in one channel or supergroup per minute.
51    pub messages_per_min_channel_or_supergroup: u32,
52
53    /// Allowed messages per second.
54    pub messages_per_sec_overall: u32,
55}
56
57impl Settings {
58    pub fn limits(mut self, val: Limits) -> Self {
59        self.limits = val;
60        self
61    }
62
63    pub fn on_queue_full<F, Fut>(mut self, mut val: F) -> Self
64    where
65        F: FnMut(usize) -> Fut + Send + 'static,
66        Fut: Future<Output = ()> + Send + 'static,
67    {
68        self.on_queue_full = Box::new(move |pending| Box::pin(val(pending)));
69        self
70    }
71
72    pub fn no_retry(mut self) -> Self {
73        self.retry = false;
74        self
75    }
76
77    pub fn check_slow_mode(mut self) -> Self {
78        self.check_slow_mode = true;
79        self
80    }
81}
82
83impl Default for Settings {
84    fn default() -> Self {
85        Self {
86            limits: <_>::default(),
87            on_queue_full: Box::new(|pending| {
88                log::warn!("Throttle queue is full ({pending} pending requests)");
89                Box::pin(ready(()))
90            }),
91            retry: true,
92            check_slow_mode: false,
93        }
94    }
95}
96
97/// Defaults are taken from [telegram documentation][tgdoc] (except for
98/// `messages_per_min_channel`).
99///
100/// [tgdoc]: https://core.telegram.org/bots/faq#my-bot-is-hitting-limits-how-do-i-avoid-this
101impl Default for Limits {
102    fn default() -> Self {
103        Self {
104            messages_per_sec_chat: 1,
105            messages_per_sec_overall: 30,
106            messages_per_min_chat: 20,
107            messages_per_min_channel_or_supergroup: 10,
108        }
109    }
110}