in packages/sqrl-redis-functions/src/lua/rateLimitFetchLua.ts [8:62]
export function rateLimitFetchLua() {
// It is likely inefficient to update the expiry time on every ratelimit,
// change, that could be optimized a lot.
return (
`
local maxAmount = tonumber(ARGV[1])
local take = tonumber(ARGV[2])
local at = tonumber(ARGV[3])
local refillTime = tonumber(ARGV[4])
local refillAmount = tonumber(ARGV[5])
local strict = tonumber(ARGV[6]) > 0
local current = redis.call("get", KEYS[1]);
local tokens
local lastRefill
if not current then
tokens = maxAmount
lastRefill = at
else
tokens, lastRefill = struct.unpack("i8i8", current)
end
if take == 0 then
return tokens
end
if tokens < take then
local refills = math.floor((at - lastRefill) / refillTime);
lastRefill = lastRefill + refills * refillTime
tokens = math.min(maxAmount, tokens + refills * refillAmount)
end
local beforeTake = tokens
if tokens == 0 then
if strict then
lastRefill = at
else
return 0
end
else
tokens = math.max(0, tokens - take)
end
local expiry = math.ceil((maxAmount - tokens) / refillAmount) * refillTime
local value = struct.pack("i8i8", tokens, lastRefill)
redis.call("set", KEYS[1], value, "px", expiry)
return beforeTake
`.trim() + "\n"
);
}