@@ -30,7 +30,7 @@ export const slidingWindowLimitScript = `
3030 local tokens = tonumber(ARGV[1]) -- tokens per window
3131 local now = ARGV[2] -- current timestamp in milliseconds
3232 local window = ARGV[3] -- interval in milliseconds
33- local incrementBy = ARGV[4] -- increment rate per request at a given value, default is 1
33+ local incrementBy = tonumber( ARGV[4]) -- increment rate per request at a given value, default is 1
3434
3535 local requestsInCurrentWindow = redis.call("GET", currentKey)
3636 if requestsInCurrentWindow == false then
@@ -44,12 +44,14 @@ export const slidingWindowLimitScript = `
4444 local percentageInCurrent = ( now % window ) / window
4545 -- weighted requests to consider from the previous window
4646 requestsInPreviousWindow = math.floor(( 1 - percentageInCurrent ) * requestsInPreviousWindow)
47- if requestsInPreviousWindow + requestsInCurrentWindow >= tokens then
47+
48+ -- Only check limit if not refunding (negative rate)
49+ if incrementBy > 0 and requestsInPreviousWindow + requestsInCurrentWindow >= tokens then
4850 return -1
4951 end
5052
5153 local newValue = redis.call("INCRBY", currentKey, incrementBy)
52- if newValue == tonumber( incrementBy) then
54+ if newValue == incrementBy then
5355 -- The first time this key is set, the value will be equal to incrementBy.
5456 -- So we only need the expire command once
5557 redis.call("PEXPIRE", currentKey, window * 2 + 1000) -- Enough time to overlap with a new window + 1 second
@@ -108,15 +110,19 @@ export const tokenBucketLimitScript = `
108110 refilledAt = refilledAt + numRefills * interval
109111 end
110112
111- if tokens == 0 then
113+ -- Only reject if tokens are 0 and we're consuming (not refunding)
114+ if tokens == 0 and incrementBy > 0 then
112115 return {-1, refilledAt + interval}
113116 end
114117
115118 local remaining = tokens - incrementBy
116119 local expireAt = math.ceil(((maxTokens - remaining) / refillRate)) * interval
117120
118121 redis.call("HSET", key, "refilledAt", refilledAt, "tokens", remaining)
119- redis.call("PEXPIRE", key, expireAt)
122+
123+ if (expireAt > 0) then
124+ redis.call("PEXPIRE", key, expireAt)
125+ end
120126 return {remaining, refilledAt + interval}
121127` ;
122128
0 commit comments