From 4f1a458fb7125af65559794449e5b4fc4ab1554a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D1=8B=D1=80=D1=86=D0=B5=D0=B2=20=D0=92=D0=B0=D0=B4?= =?UTF-8?q?=D0=B8=D0=BC=20=D0=98=D0=B3=D0=BE=D1=80=D0=B5=D0=B2=D0=B8=D1=87?= Date: Sun, 28 Jul 2024 13:03:21 +0300 Subject: [PATCH] Refactor backoff-related code --- CHANGELOG.md | 2 +- Cargo.lock | 84 ------------------- crates/teloxide-core/CHANGELOG.md | 2 +- crates/teloxide/Cargo.toml | 1 - crates/teloxide/src/backoff.rs | 23 ++--- .../teloxide/src/update_listeners/polling.rs | 19 +++-- 6 files changed, 24 insertions(+), 107 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cf5bfc08..3908977c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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)) - 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]) -- 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 diff --git a/Cargo.lock b/Cargo.lock index d8044db3..23d9fb70 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -691,12 +691,6 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" -[[package]] -name = "futures-timer" -version = "3.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" - [[package]] name = "futures-util" version = "0.3.30" @@ -742,12 +736,6 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" -[[package]] -name = "glob" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" - [[package]] name = "h2" version = "0.3.26" @@ -1456,15 +1444,6 @@ dependencies = [ "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]] name = "proc-macro-error" version = "1.0.4" @@ -1618,12 +1597,6 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" -[[package]] -name = "relative-path" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" - [[package]] name = "reqwest" version = "0.11.27" @@ -1698,36 +1671,6 @@ dependencies = [ "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]] name = "rustc-demangle" version = "0.1.24" @@ -2278,7 +2221,6 @@ dependencies = [ "pretty_env_logger 0.5.0", "rand", "reqwest", - "rstest", "serde", "serde_cbor", "serde_json", @@ -2469,23 +2411,6 @@ dependencies = [ "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]] name = "tower" version = "0.4.13" @@ -2972,15 +2897,6 @@ version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" -[[package]] -name = "winnow" -version = "0.5.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" -dependencies = [ - "memchr", -] - [[package]] name = "winreg" version = "0.50.0" diff --git a/crates/teloxide-core/CHANGELOG.md b/crates/teloxide-core/CHANGELOG.md index d7c6f094..262f99cc 100644 --- a/crates/teloxide-core/CHANGELOG.md +++ b/crates/teloxide-core/CHANGELOG.md @@ -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 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]) -- 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 [pr879]: https://github.com/teloxide/teloxide/pull/879 diff --git a/crates/teloxide/Cargo.toml b/crates/teloxide/Cargo.toml index 0d88e627..a752cd7e 100644 --- a/crates/teloxide/Cargo.toml +++ b/crates/teloxide/Cargo.toml @@ -126,7 +126,6 @@ tokio = { version = "1.8", features = ["fs", "rt-multi-thread", "macros"] } reqwest = "0.11.11" chrono = "0.4" tokio-stream = "0.1" -rstest = "0.21.0" [package.metadata.docs.rs] diff --git a/crates/teloxide/src/backoff.rs b/crates/teloxide/src/backoff.rs index efafef07..24ff91c9 100644 --- a/crates/teloxide/src/backoff.rs +++ b/crates/teloxide/src/backoff.rs @@ -2,8 +2,6 @@ use std::time::Duration; pub type BackoffStrategy = Box Duration>; -const THRESHOLD_ERROR_QUANTITY: u32 = 6; - /// 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 @@ -12,20 +10,23 @@ const THRESHOLD_ERROR_QUANTITY: u32 = 6; /// More at: pub fn exponential_backoff_strategy(error_count: u32) -> Duration { // 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)] mod tests { - use rstest::rstest; - use super::*; - #[rstest] - #[case(1, Duration::from_secs(2))] - #[case(5, Duration::from_secs(32))] - #[case(42, Duration::from_secs(64))] - fn test_exponential_backoff_strategy(#[case] error_count: u32, #[case] expected: Duration) { - assert_eq!(exponential_backoff_strategy(error_count), expected); + #[test] + fn test_exponential_backoff_strategy() { + let cases = [ + (1, Duration::from_secs(2)), + (5, Duration::from_secs(32)), + (42, Duration::from_secs(64)), + ]; + + for (error_count, expected) in cases { + assert_eq!(exponential_backoff_strategy(error_count), expected); + } } } diff --git a/crates/teloxide/src/update_listeners/polling.rs b/crates/teloxide/src/update_listeners/polling.rs index f55777e4..a7a8f010 100644 --- a/crates/teloxide/src/update_listeners/polling.rs +++ b/crates/teloxide/src/update_listeners/polling.rs @@ -425,7 +425,7 @@ impl Stream for PollingStream<'_, B> { return Ready(Some(Err(err))); } 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; if let Some(upd) = updates.last() { @@ -445,14 +445,15 @@ impl Stream for PollingStream<'_, B> { Otherwise, in case of network connection lose () we use the backoff strategy to prevent the high CPU usage due to multiple instant reconnections */ - if let Some(seconds) = err.retry_after() { - log::info!("got `RetryAfter({})` error, polling paused", seconds); - this.eepy.set(Some(sleep(seconds.duration()))); - } else { - let delay = (this.polling.backoff_strategy)(*this.error_count); - log::info!("retrying getting updates in {}s", delay.as_secs()); - this.eepy.set(Some(sleep(delay))); - } + let delay = match err.retry_after() { + Some(seconds) => { + *this.error_count = 0; + seconds.duration() + } + None => (this.polling.backoff_strategy)(*this.error_count), + }; + log::info!("retrying getting updates in {}s", delay.as_secs()); + this.eepy.set(Some(sleep(delay))); return Ready(Some(Err(err))); }