Skip to content
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

ratelimit: redis should retry if allowed requests exceeded #789

Merged
merged 1 commit into from
Mar 4, 2024

Conversation

bkylerussell
Copy link
Contributor

Implements retry on Take() for NewRedisLimiter, and now correctly logs debug message when throttling occurs.

When configured to use redis, ratelimiting has always been least effort. While Take() may sleep for the requested RetryAfter time, NewRedisLimiter never re-checks to see if we're actually allowed to make further requests after the RetryAfter time expires. By re-checking Allow(), this actually enforces the desired ratelimit when multiple routines are scheduled simultaneously.

This is not an issue with NewLocalLimiter since Limiter.Wait() will block until an event is allowed (or error with log.Fatal(), terminating the application).

Additionally, the "throttled GitLab requests" message was never useful under its previous conditions. Both NewRedisLimiter and NewLocalLimiter are calculating start.Sub(time.Now()) from the end of the function, which always returns a negative Duration, meaning the condition was never satisfied.

Since NewLocalLimiter is already throttling correctly via Wait(), and since any non-successful return from Limiter.Wait() terminates the application via log.Fatal(); this means this "throttled" log message is likely only useful in NewRedisLimiter (when it retries).

@mvisonneau
Copy link
Owner

Thanks a ton for this fix @bkylerussell! Do you mind looking into the failing tests?

Implements retry on Take() for NewRedisLimiter, and now correctly logs debug
message when throttling occurs.

When configured to use redis, ratelimiting has always been least effort. While
Take() may sleep for the requested RetryAfter time, NewRedisLimiter never
re-checks to see if we're actually allowed to make further requests after
the RetryAfter time expires. By re-checking Allow(), this actually enforces
the desired ratelimit when multiple routines are scheduled simultaneously.

This is not an issue with NewLocalLimiter since Limiter.Wait() will block until
an event is allowed (or error with log.Fatal(), terminating the application).

Additionally, the "throttled GitLab requests" message was never useful under its
previous conditions. Both NewRedisLimiter and NewLocalLimiter are calculating
`start.Sub(time.Now())` from the end of the function, which always returns a
negative Duration, meaning the condition was never satisfied.

Since NewLocalLimiter is already throttling correctly via Wait(), and since any
non-successful return from Limiter.Wait() terminates the application via
log.Fatal(); this means this "throttled" log message is likely only useful
in NewRedisLimiter (when it retries).
@mvisonneau
Copy link
Owner

thanks again!

@mvisonneau mvisonneau merged commit 7540b1a into mvisonneau:main Mar 4, 2024
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants