Skip to content

[RateLimiter] fix incorrect retryAfter of FixedWindow #49070

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 13, 2023

Conversation

RobertMe
Copy link
Contributor

Q A
Branch? 5.4
Bug fix? yes
New feature? no
Deprecations? no
Tickets
License MIT
Doc PR

A FixedWindow always ends intervalInSeconds after the start time (timer). So when calculating the time to consume some tokens the tokens will always be available at timer + intervalInSeconds. But currently this is reported incorrectly as calculateTimeForTokens() calculates the time based on the desired amount of tokens (and cycles) while it doesn't take into account maxSize amount of tokens become available at the windows end.

Furthermore calculating the amount of needed cycles is incorrect. This as all tokens become available at once (at the windows end) and you can't consume more tokens than maxSize (which is validated at the start of FixedWindowLimiter::reserve, in case of tokens > limit it throws).

Note: I don't think that changing the signature of calculateTimeForTokens is a deprecation. This as the Window class is marked as @internal. So it should only be used by the RateLimiter component.

@RobertMe
Copy link
Contributor Author

I'm uncertain about the Psalm failure. return ceil(...) results in a float (while it is an integer value), and the return type is declared as int. But the old code also was based on ceil() resulting in a float return value, while the return type was declared as int. So I guess that's fine?

@Robert-Embloom
Copy link
Contributor

@wouterj it seems like you're the original developer of the RateLimiter component. So may I ask you to have a look at this? (as it seems to have gone unnoticed in general)

@RobertMe RobertMe force-pushed the fixed-window-retry-after branch from c612584 to 5c380e9 Compare July 10, 2023 10:31
A FixedWindow always ends `intervalInSeconds` after the start time
(`timer`). So when calculating the time to consume some tokens the
tokens will always be available at `timer + intervalInSeconds`. But
currently this is reported incorrectly as `calculateTimeForTokens()`
calculates the time based on the desired amount of tokens (and cycles)
while it doesn't take into account `maxSize` amount of tokens become
available at the windows end.

Furthermore calculating the amount of needed cycles is incorrect. This
as all tokens become available at once (at the windows end) and you
can't consume more tokens than `maxSize` (which is validated at the
start of `FixedWindowLimiter::reserve`, in case of `tokens > limit` it
throws).
@RobertMe RobertMe force-pushed the fixed-window-retry-after branch from 5c380e9 to 2316932 Compare July 10, 2023 11:11
@fabpot
Copy link
Member

fabpot commented Jul 13, 2023

Thank you @RobertMe.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants