Update 2025-04-24_11:44:19
This commit is contained in:
@ -0,0 +1,26 @@
|
||||
local timestamp = tonumber(ARGV[1])
|
||||
local limit = tonumber(ARGV[2])
|
||||
local expiry = tonumber(ARGV[3])
|
||||
local amount = tonumber(ARGV[4])
|
||||
|
||||
if amount > limit then
|
||||
return false
|
||||
end
|
||||
|
||||
local entry = redis.call('lindex', KEYS[1], limit - amount)
|
||||
|
||||
if entry and tonumber(entry) >= timestamp - expiry then
|
||||
return false
|
||||
end
|
||||
local entries = {}
|
||||
for i = 1, amount do
|
||||
entries[i] = timestamp
|
||||
end
|
||||
|
||||
for i=1,#entries,5000 do
|
||||
redis.call('lpush', KEYS[1], unpack(entries, i, math.min(i+4999, #entries)))
|
||||
end
|
||||
redis.call('ltrim', KEYS[1], 0, limit - 1)
|
||||
redis.call('expire', KEYS[1], expiry)
|
||||
|
||||
return true
|
@ -0,0 +1,45 @@
|
||||
-- Time is in milliseconds in this script: TTL, expiry...
|
||||
|
||||
local limit = tonumber(ARGV[1])
|
||||
local expiry = tonumber(ARGV[2]) * 1000
|
||||
local amount = tonumber(ARGV[3])
|
||||
|
||||
if amount > limit then
|
||||
return false
|
||||
end
|
||||
|
||||
local current_ttl = tonumber(redis.call('pttl', KEYS[2]))
|
||||
|
||||
if current_ttl > 0 and current_ttl < expiry then
|
||||
-- Current window expired, shift it to the previous window
|
||||
redis.call('rename', KEYS[2], KEYS[1])
|
||||
redis.call('set', KEYS[2], 0, 'PX', current_ttl + expiry)
|
||||
end
|
||||
|
||||
local previous_count = tonumber(redis.call('get', KEYS[1])) or 0
|
||||
local previous_ttl = tonumber(redis.call('pttl', KEYS[1])) or 0
|
||||
local current_count = tonumber(redis.call('get', KEYS[2])) or 0
|
||||
current_ttl = tonumber(redis.call('pttl', KEYS[2])) or 0
|
||||
|
||||
-- If the values don't exist yet, consider the TTL is 0
|
||||
if previous_ttl <= 0 then
|
||||
previous_ttl = 0
|
||||
end
|
||||
if current_ttl <= 0 then
|
||||
current_ttl = 0
|
||||
end
|
||||
local weighted_count = math.floor(previous_count * previous_ttl / expiry) + current_count
|
||||
|
||||
if (weighted_count + amount) > limit then
|
||||
return false
|
||||
end
|
||||
|
||||
-- If the current counter exists, increase its value
|
||||
if redis.call('exists', KEYS[2]) == 1 then
|
||||
redis.call('incrby', KEYS[2], amount)
|
||||
else
|
||||
-- Otherwise, set the value with twice the expiry time
|
||||
redis.call('set', KEYS[2], amount, 'PX', expiry * 2)
|
||||
end
|
||||
|
||||
return true
|
@ -0,0 +1,10 @@
|
||||
local keys = redis.call('keys', KEYS[1])
|
||||
local res = 0
|
||||
|
||||
for i=1,#keys,5000 do
|
||||
res = res + redis.call(
|
||||
'del', unpack(keys, i, math.min(i+4999, #keys))
|
||||
)
|
||||
end
|
||||
|
||||
return res
|
@ -0,0 +1,9 @@
|
||||
local current
|
||||
local amount = tonumber(ARGV[2])
|
||||
current = redis.call("incrby", KEYS[1], amount)
|
||||
|
||||
if tonumber(current) == amount then
|
||||
redis.call("expire", KEYS[1], ARGV[1])
|
||||
end
|
||||
|
||||
return current
|
@ -0,0 +1,30 @@
|
||||
local len = tonumber(ARGV[2])
|
||||
local expiry = tonumber(ARGV[1])
|
||||
|
||||
-- Binary search to find the oldest valid entry in the window
|
||||
local function oldest_entry(high, target)
|
||||
local low = 0
|
||||
local result = nil
|
||||
|
||||
while low <= high do
|
||||
local mid = math.floor((low + high) / 2)
|
||||
local val = tonumber(redis.call('lindex', KEYS[1], mid))
|
||||
|
||||
if val and val >= target then
|
||||
result = mid
|
||||
low = mid + 1
|
||||
else
|
||||
high = mid - 1
|
||||
end
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
local index = oldest_entry(len - 1, expiry)
|
||||
|
||||
if index then
|
||||
local count = index + 1
|
||||
local oldest = tonumber(redis.call('lindex', KEYS[1], index))
|
||||
return {tostring(oldest), count}
|
||||
end
|
@ -0,0 +1,17 @@
|
||||
local expiry = tonumber(ARGV[1]) * 1000
|
||||
local previous_count = redis.call('get', KEYS[1])
|
||||
local previous_ttl = redis.call('pttl', KEYS[1])
|
||||
local current_count = redis.call('get', KEYS[2])
|
||||
local current_ttl = redis.call('pttl', KEYS[2])
|
||||
|
||||
if current_ttl > 0 and current_ttl < expiry then
|
||||
-- Current window expired, shift it to the previous window
|
||||
redis.call('rename', KEYS[2], KEYS[1])
|
||||
redis.call('set', KEYS[2], 0, 'PX', current_ttl + expiry)
|
||||
previous_count = redis.call('get', KEYS[1])
|
||||
previous_ttl = redis.call('pttl', KEYS[1])
|
||||
current_count = redis.call('get', KEYS[2])
|
||||
current_ttl = redis.call('pttl', KEYS[2])
|
||||
end
|
||||
|
||||
return {previous_count, previous_ttl, current_count, current_ttl}
|
Reference in New Issue
Block a user