mirror of
https://github.com/teloxide/teloxide.git
synced 2024-12-22 22:46:39 +01:00
Refactor backoff-related code
This commit is contained in:
parent
87188d5dea
commit
4f1a458fb7
6 changed files with 24 additions and 107 deletions
|
@ -67,7 +67,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
- Feature `sqlite-storage` was renamed to `sqlite-storage-nativetls`([PR 995](https://github.com/teloxide/teloxide/pull/995))
|
- Feature `sqlite-storage` was renamed to `sqlite-storage-nativetls`([PR 995](https://github.com/teloxide/teloxide/pull/995))
|
||||||
- MSRV (Minimal Supported Rust Version) was bumped from `1.68.0` to `1.70.0` ([PR 996][https://github.com/teloxide/teloxide/pull/996])
|
- MSRV (Minimal Supported Rust Version) was bumped from `1.68.0` to `1.70.0` ([PR 996][https://github.com/teloxide/teloxide/pull/996])
|
||||||
- `axum` was bumped to `0.7`, along with related libraries used for webhooks ([PR 1093][https://github.com/teloxide/teloxide/pull/1093])
|
- `axum` was bumped to `0.7`, along with related libraries used for webhooks ([PR 1093][https://github.com/teloxide/teloxide/pull/1093])
|
||||||
- Exponential backoff now results in 64 seconds maximum delay instead of 17 minutes ([PR 1113][https://github.com/teloxide/teloxide/pull/1113])
|
- `Polling`'s exponential backoff now results in 64 seconds maximum delay instead of 17 minutes ([PR 1113][https://github.com/teloxide/teloxide/pull/1113])
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
|
|
84
Cargo.lock
generated
84
Cargo.lock
generated
|
@ -691,12 +691,6 @@ version = "0.3.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
|
checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "futures-timer"
|
|
||||||
version = "3.0.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-util"
|
name = "futures-util"
|
||||||
version = "0.3.30"
|
version = "0.3.30"
|
||||||
|
@ -742,12 +736,6 @@ version = "0.29.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd"
|
checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "glob"
|
|
||||||
version = "0.3.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "h2"
|
name = "h2"
|
||||||
version = "0.3.26"
|
version = "0.3.26"
|
||||||
|
@ -1456,15 +1444,6 @@ dependencies = [
|
||||||
"log",
|
"log",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "proc-macro-crate"
|
|
||||||
version = "3.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284"
|
|
||||||
dependencies = [
|
|
||||||
"toml_edit",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro-error"
|
name = "proc-macro-error"
|
||||||
version = "1.0.4"
|
version = "1.0.4"
|
||||||
|
@ -1618,12 +1597,6 @@ version = "0.8.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
|
checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "relative-path"
|
|
||||||
version = "1.9.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "reqwest"
|
name = "reqwest"
|
||||||
version = "0.11.27"
|
version = "0.11.27"
|
||||||
|
@ -1698,36 +1671,6 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rstest"
|
|
||||||
version = "0.21.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9afd55a67069d6e434a95161415f5beeada95a01c7b815508a82dcb0e1593682"
|
|
||||||
dependencies = [
|
|
||||||
"futures",
|
|
||||||
"futures-timer",
|
|
||||||
"rstest_macros",
|
|
||||||
"rustc_version",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rstest_macros"
|
|
||||||
version = "0.21.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4165dfae59a39dd41d8dec720d3cbfbc71f69744efb480a3920f5d4e0cc6798d"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"glob",
|
|
||||||
"proc-macro-crate",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"regex",
|
|
||||||
"relative-path",
|
|
||||||
"rustc_version",
|
|
||||||
"syn 2.0.52",
|
|
||||||
"unicode-ident",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-demangle"
|
name = "rustc-demangle"
|
||||||
version = "0.1.24"
|
version = "0.1.24"
|
||||||
|
@ -2278,7 +2221,6 @@ dependencies = [
|
||||||
"pretty_env_logger 0.5.0",
|
"pretty_env_logger 0.5.0",
|
||||||
"rand",
|
"rand",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"rstest",
|
|
||||||
"serde",
|
"serde",
|
||||||
"serde_cbor",
|
"serde_cbor",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
@ -2469,23 +2411,6 @@ dependencies = [
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "toml_datetime"
|
|
||||||
version = "0.6.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f8fb9f64314842840f1d940ac544da178732128f1c78c21772e876579e0da1db"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "toml_edit"
|
|
||||||
version = "0.21.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1"
|
|
||||||
dependencies = [
|
|
||||||
"indexmap 2.2.5",
|
|
||||||
"toml_datetime",
|
|
||||||
"winnow",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tower"
|
name = "tower"
|
||||||
version = "0.4.13"
|
version = "0.4.13"
|
||||||
|
@ -2972,15 +2897,6 @@ version = "0.52.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"
|
checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "winnow"
|
|
||||||
version = "0.5.40"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876"
|
|
||||||
dependencies = [
|
|
||||||
"memchr",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winreg"
|
name = "winreg"
|
||||||
version = "0.50.0"
|
version = "0.50.0"
|
||||||
|
|
|
@ -107,7 +107,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
- Deserialization of `ApiError::CantParseEntities` ([#839][pr839])
|
- Deserialization of `ApiError::CantParseEntities` ([#839][pr839])
|
||||||
- Deserialization of empty (content-less) messages that can sometimes appear as a part of callback query ([#850][pr850], issue [#873][issue873])
|
- Deserialization of empty (content-less) messages that can sometimes appear as a part of callback query ([#850][pr850], issue [#873][issue873])
|
||||||
- Type of `chat_id` in `send_game`: `u32` => `ChatId` ([#1066][pr1066])
|
- Type of `chat_id` in `send_game`: `u32` => `ChatId` ([#1066][pr1066])
|
||||||
- In case of `RetryAfter(..)` errors the polling is paused for the specified delay instead of falling into the backoff strategy ([#1113][pr1113])
|
- `Requester::Err` was bounded to the `AsResponseParameters`. In case of `RetryAfter(..)` errors the polling is paused for the specified delay instead of falling into the backoff strategy ([#1113][pr1113])
|
||||||
|
|
||||||
[pr839]: https://github.com/teloxide/teloxide/pull/839
|
[pr839]: https://github.com/teloxide/teloxide/pull/839
|
||||||
[pr879]: https://github.com/teloxide/teloxide/pull/879
|
[pr879]: https://github.com/teloxide/teloxide/pull/879
|
||||||
|
|
|
@ -126,7 +126,6 @@ tokio = { version = "1.8", features = ["fs", "rt-multi-thread", "macros"] }
|
||||||
reqwest = "0.11.11"
|
reqwest = "0.11.11"
|
||||||
chrono = "0.4"
|
chrono = "0.4"
|
||||||
tokio-stream = "0.1"
|
tokio-stream = "0.1"
|
||||||
rstest = "0.21.0"
|
|
||||||
|
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
|
|
|
@ -2,8 +2,6 @@ use std::time::Duration;
|
||||||
|
|
||||||
pub type BackoffStrategy = Box<dyn Send + Fn(u32) -> Duration>;
|
pub type BackoffStrategy = Box<dyn Send + Fn(u32) -> Duration>;
|
||||||
|
|
||||||
const THRESHOLD_ERROR_QUANTITY: u32 = 6;
|
|
||||||
|
|
||||||
/// Calculates the backoff time in seconds for exponential strategy with base 2
|
/// Calculates the backoff time in seconds for exponential strategy with base 2
|
||||||
///
|
///
|
||||||
/// The maximum duration is limited to a little more than a minute: 64s, so the
|
/// The maximum duration is limited to a little more than a minute: 64s, so the
|
||||||
|
@ -12,20 +10,23 @@ const THRESHOLD_ERROR_QUANTITY: u32 = 6;
|
||||||
/// More at: <https://en.wikipedia.org/wiki/Exponential_backoff#Exponential_backoff_algorithm>
|
/// More at: <https://en.wikipedia.org/wiki/Exponential_backoff#Exponential_backoff_algorithm>
|
||||||
pub fn exponential_backoff_strategy(error_count: u32) -> Duration {
|
pub fn exponential_backoff_strategy(error_count: u32) -> Duration {
|
||||||
// 2^6 = 64s ~ a little more than a minute
|
// 2^6 = 64s ~ a little more than a minute
|
||||||
Duration::from_secs(1_u64 << error_count.min(THRESHOLD_ERROR_QUANTITY))
|
Duration::from_secs(1_u64 << error_count.min(6))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use rstest::rstest;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[rstest]
|
#[test]
|
||||||
#[case(1, Duration::from_secs(2))]
|
fn test_exponential_backoff_strategy() {
|
||||||
#[case(5, Duration::from_secs(32))]
|
let cases = [
|
||||||
#[case(42, Duration::from_secs(64))]
|
(1, Duration::from_secs(2)),
|
||||||
fn test_exponential_backoff_strategy(#[case] error_count: u32, #[case] expected: Duration) {
|
(5, Duration::from_secs(32)),
|
||||||
|
(42, Duration::from_secs(64)),
|
||||||
|
];
|
||||||
|
|
||||||
|
for (error_count, expected) in cases {
|
||||||
assert_eq!(exponential_backoff_strategy(error_count), expected);
|
assert_eq!(exponential_backoff_strategy(error_count), expected);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -425,7 +425,7 @@ impl<B: Requester> Stream for PollingStream<'_, B> {
|
||||||
return Ready(Some(Err(err)));
|
return Ready(Some(Err(err)));
|
||||||
}
|
}
|
||||||
Ok(updates) => {
|
Ok(updates) => {
|
||||||
// Once we got the update hense the backoff reconnection strategy worked
|
// Once we got the update the backoff reconnection strategy worked
|
||||||
*this.error_count = 0;
|
*this.error_count = 0;
|
||||||
|
|
||||||
if let Some(upd) = updates.last() {
|
if let Some(upd) = updates.last() {
|
||||||
|
@ -445,14 +445,15 @@ impl<B: Requester> Stream for PollingStream<'_, B> {
|
||||||
Otherwise, in case of network connection lose (<https://github.com/teloxide/teloxide/issues/780>) we
|
Otherwise, in case of network connection lose (<https://github.com/teloxide/teloxide/issues/780>) we
|
||||||
use the backoff strategy to prevent the high CPU usage due to multiple instant reconnections
|
use the backoff strategy to prevent the high CPU usage due to multiple instant reconnections
|
||||||
*/
|
*/
|
||||||
if let Some(seconds) = err.retry_after() {
|
let delay = match err.retry_after() {
|
||||||
log::info!("got `RetryAfter({})` error, polling paused", seconds);
|
Some(seconds) => {
|
||||||
this.eepy.set(Some(sleep(seconds.duration())));
|
*this.error_count = 0;
|
||||||
} else {
|
seconds.duration()
|
||||||
let delay = (this.polling.backoff_strategy)(*this.error_count);
|
}
|
||||||
|
None => (this.polling.backoff_strategy)(*this.error_count),
|
||||||
|
};
|
||||||
log::info!("retrying getting updates in {}s", delay.as_secs());
|
log::info!("retrying getting updates in {}s", delay.as_secs());
|
||||||
this.eepy.set(Some(sleep(delay)));
|
this.eepy.set(Some(sleep(delay)));
|
||||||
}
|
|
||||||
|
|
||||||
return Ready(Some(Err(err)));
|
return Ready(Some(Err(err)));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue