Fix calculation of per-second used counts in throttling

This is not the cause of throttling issues that I was having, but
something I think is a bug from reading the code.

`history` is a deque that is kept sorted by the timestamp: old entries
are popped from the front, and new entries are pushed to the back. To
calculate `used` and `requests_sent.per_sec[chat]`, we want to count
entries from the past second, so the newest ones, so from the back.

For `take_while` to work as expected, it needs to be called on the
reverse iterator, as the regular iterator is front-to-back. Otherwise
`take_while` can finish early due to entries that are up to a minute
old.
This commit is contained in:
Ilya Bizyaev 2024-12-06 22:52:27 +01:00
parent 94db1757dc
commit 146d42de37
No known key found for this signature in database
GPG key ID: 29AACC9F9F66C5B4
2 changed files with 3 additions and 2 deletions

View file

@ -33,6 +33,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Now `InlineQueryResultsButton` serializes properly ([issue 1181](https://github.com/teloxide/teloxide/issues/1181))
- Now `ThreadId` is able to serialize in multipart requests ([PR 1179](https://github.com/teloxide/teloxide/pull/1179))
- Now stack does not overflow on dispatch ([issue 1154](https://github.com/teloxide/teloxide/issues/1154))
- Fixed calculation of per-second limits in the `Throttle` adaptor ([PR 1212](https://github.com/teloxide/teloxide/pull/1212))
## 0.13.0 - 2024-08-16

View file

@ -213,7 +213,7 @@ pub(super) async fn worker<B>(
// as truncates which is ok since in case of truncation it would always be >=
// limits.overall_s
let used = history.iter().take_while(|(_, time)| time > &sec_back).count() as u32;
let used = history.iter().rev().take_while(|(_, time)| time > &sec_back).count() as u32;
let mut allowed = limits.messages_per_sec_overall.saturating_sub(used);
if allowed == 0 {
@ -222,7 +222,7 @@ pub(super) async fn worker<B>(
continue;
}
for (chat, _) in history.iter().take_while(|(_, time)| time > &sec_back) {
for (chat, _) in history.iter().rev().take_while(|(_, time)| time > &sec_back) {
*requests_sent.per_sec.entry(*chat).or_insert(0) += 1;
}