Skip to content

Strategy/token bucket - #122

Merged
ArnabChatterjee20k merged 8 commits into
strategy/sliding-windowfrom
strategy/token-bucket
Aug 13, 2026
Merged

Strategy/token bucket#122
ArnabChatterjee20k merged 8 commits into
strategy/sliding-windowfrom
strategy/token-bucket

Conversation

@ArnabChatterjee20k

Copy link
Copy Markdown
Contributor

No description provided.

Introduce the storage-agnostic TokenBucket adapter (mirrors SlidingWindow:
count()/remaining()/limit()/time()) and RedisBase, which owns the atomic
refill-and-consume Lua script, a read-only refill estimate and the
eval()/delete() seams. Bucket state is a single Redis hash; ttl is derived
from capacity/refillRate.
Concrete adapters implementing the eval()/delete() seams plus getLogs()
(reads bucket hashes via hGetAll). Constructor takes (key, tokens, refillRate).
Shared Base suite covering burst/capacity, remaining, refill over time,
reset, refill-rate guard and unlimited (tokens 0).
@greptile-apps

greptile-apps Bot commented Aug 13, 2026

Copy link
Copy Markdown

Greptile Summary

The PR adds token-bucket rate limiting backed by Redis, Redis Cluster, pooled Redis connections, and a no-op adapter. The latest changes refresh token balances when calculating remaining capacity and fully enumerate cluster keys before globally sorting and paginating them.

  • Adds atomic Lua-based refill and consumption logic.
  • Adds reset, cleanup, log retrieval, unlimited-limit handling, and configuration validation.
  • Adds shared behavioral tests for Redis-backed token-bucket adapters.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains; the stale remaining-count path now performs a fresh refill-aware read, and cluster pagination now scans the complete candidate set before sorting and slicing.

Important Files Changed

Filename Overview
src/Abuse/Adapters/TokenBucket.php Defines the token-bucket contract and computes remaining quota using the established consumed-count convention.
src/Abuse/Adapters/TokenBucket/RedisBase.php Implements atomic refill and consumption while the fresh read-only token calculation resolves the previously stale remaining count.
src/Abuse/Adapters/TokenBucket/RedisCluster.php Fully scans every cluster master before global sorting and slicing, resolving the previously biased pagination.
src/Abuse/Adapters/TokenBucket/RedisPool.php Provides pooled Redis and Redis Cluster execution with complete log enumeration before pagination.
tests/Abuse/TokenBucket/Base.php Covers capacity, dynamic keys, bursts, remaining quota, refill, reset, validation, and unlimited operation.

Fix All in Greploop

Reviews (4): Last reviewed commit: "Merge branch 'strategy/sliding-window' i..." | Re-trigger Greptile

Comment thread src/Abuse/Adapters/TokenBucket/RedisBase.php Outdated
Comment thread src/Abuse/Adapters/TokenBucket/RedisCluster.php Outdated
…ount

Fractional refill made floor(capacity - balance) undercount consumed tokens
by one (e.g. balance 1.00001 -> 1 consumed instead of 2). Floor the available
balance first, then subtract from capacity so remaining() stays exact.
The bucket refills continuously, so caching the consumed count made
remaining() report a stale quota once time elapsed after a check(). Drop the
cache and compute a fresh estimate on every count(); check() now only needs
the allow decision.
…logs

Stopping each master's unordered scan at offset+limit and then sorting/slicing
the partial candidate set returned a biased page and could omit keys in range.
Scan all masters completely, then sort and slice.
@ArnabChatterjee20k
ArnabChatterjee20k merged commit d75bb51 into strategy/sliding-window Aug 13, 2026
6 checks passed
@ArnabChatterjee20k
ArnabChatterjee20k deleted the strategy/token-bucket branch August 13, 2026 11:29
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.

1 participant