-- Absolute limit quota grant script (the fairness partial is prepended by RuleExecutor).
-- KEYS[1]: quota key (counter)
-- KEYS[2]: waiters key (sorted set of waiters, see partials/fairness.lua)
-- ARGV[1]: limit
-- ARGV[2]: waiterId ('' for a fresh, non-waiting caller)
-- ARGV[3]: maxWait (ms) of the caller
-- ARGV[4]: mayWait (1 = register as waiter on denial, 0 = never)
-- Returns: {granted (0/1), currentCount, retryIn (always -1 — capacity frees only via rollback,
--          which wakes waiters through a PUBLISH, or never)}

local limit = tonumber(ARGV[1])
local now = now_ms()

local currentCount = tonumber(redis.call('GET', KEYS[1]) or '0')
local free = limit - currentCount
local ahead = waiters_ahead(KEYS[2], ARGV[2], now)

if ahead < free then
    currentCount = redis.call('INCR', KEYS[1])
    deregister_waiter(KEYS[2], ARGV[2], ARGV[3])
    return { 1, currentCount, -1 }
end

if tonumber(ARGV[4]) == 1 then
    register_waiter(KEYS[2], ARGV[2], ARGV[3])
end

return { 0, currentCount, -1 }
