Skip to content

Stop the rate-limit counter from wrapping below zero - #586

Open
shri30yans wants to merge 1 commit into
redlib-org:mainfrom
shri30yans:fix/rate-limit-counter-wrap
Open

shri30yans wants to merge 1 commit into
redlib-org:mainfrom
shri30yans:fix/rate-limit-counter-wrap

Conversation

@shri30yans

Copy link
Copy Markdown

Fixes #585

How redlib keeps track

  • Reddit allows ~100 requests per minute. Redlib stores its estimate of what is left in a counter called OAUTH_RATELIMIT_REMAINING, and each request to Reddit lowers it by 1 before the request is even sent, so concurrent requests are each accounted for.

What happens today

  • When the counter reads below 10, redlib gets a fresh login token. The limit resets to 100, and users never notice the switch.

Why it breaks

  • The counter is a u16, and the code uses fetch_sub(1). Subtracting 1 from 0 wraps to 65535.
  • When several requests go out together near the end of the quota, the counter crosses zero and lands near 65535.
  • Requests arriving in that window read a big number, see no problem, and skip the token refresh. That is the one moment the refresh exists for.

The change

  • One helper, burn_rate_limit_unit(), does the decrement with fetch_update and saturating_sub: subtract, but never below 0. It is still safe when many threads decrement at once.
  • json() calls the helper instead of fetch_sub. That is the entire production change.

Tests

Four new tests, isolated so they do not clash with the network tests. On the old code, three fail with the counter reading 65535. On the new code, all four pass.

OAUTH_RATELIMIT_REMAINING is decremented speculatively with fetch_sub(1)
before every upstream request. On a u16 this wraps at zero: a burst of
concurrent requests crossing zero flips the estimate to ~65535, and the
current_rate_limit < 10 check in json() then skips the proactive OAuth
token rollover exactly when it is needed.

Move the decrement into burn_rate_limit_unit(), which saturates at 0 via
a fetch_update CAS loop, and add four regression tests. The three
wrap-behavior tests fail against the previous code (observed 65535) and
pass with the fix.
@shri30yans
shri30yans force-pushed the fix/rate-limit-counter-wrap branch from f9709fb to bcb0feb Compare October 11, 2026 18:53
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.

Rate-limit counter wraps from 0 to 65535 and skips the token refresh

1 participant