feat: implement is_negative_hits in rate limit descriptor#1140
Conversation
Signed-off-by: Rudrakh Panigrahi <rudrakh97@gmail.com>
collin-lee
left a comment
There was a problem hiding this comment.
- Redis Cluster Routing Bug (src/redis/fixed_cache_impl.go:41)
pipelineAppendDecrement passes the Lua script text as the key parameter to PipeAppend. In Redis Cluster mode, PipelineAction.Key is used to determine which slot/node to route to. This means EVAL commands would be routed incorrectly — potentially causing
MOVED/CROSSSLOT errors or silent misrouting when multiple negative-hit descriptors target different hash slots.
- Negative Hits Can Return OVER_LIMIT (src/redis/fixed_cache_impl.go:222)
The PR claims "Negative hits bypass over-limit checks (always return OK)", but this is only true for the local-cache over-limit check. In the response loop, if the post-decrement counter is still above the threshold (e.g., counter at 15, limit 10,
decrement 3 → result 12 > limit 10), GetResponseDescriptorStatus returns OVER_LIMIT. Same issue exists in memcached (src/memcached/cache_impl.go:146).
- Lua Script Returns new_val Instead of math.floor(new_val) (src/limiter/base_limiter.go:23)
Minor inconsistency: the script stores math.floor(new_val) via SET but returns new_val directly. Practically identical for integer math but easy to fix for defensive correctness.
Minor Issues
- A decrement on a non-existent key creates a phantom key at value 0 with full TTL (functionally harmless but wastes memory)
- No test coverage for negative hits with stopCacheKeyIncrementWhenOverlimit=true
- No test for negative hits when the post-decrement value is still above the limit
Suggestions
- Fix cluster routing by passing the actual Redis key (not the script) as the routing key for EVAL commands
- Force OK response for negative hits in the response handling loop (or document that OVER_LIMIT is possible)
- Add test cases for the above edge cases
Summary
Add support for the
is_negative_hitsfield on rate limit descriptors. When set, thehits_addend value decrements the rate limit counter instead of incrementing it, effectively
refilling previously consumed tokens. The counter is floored at 0 (cannot go negative).
total_negative_hitsstat tracks requested decrements per descriptorFixes envoyproxy/envoy#41219