1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
|
redis.replicate_commands()
local key = KEYS[1] local capacity = tonumber(ARGV[1]) local quota = tonumber(ARGV[2]) local period = tonumber(ARGV[3]) local quantity = tonumber(ARGV[4]) or 1 local timestamp = tonumber(redis.call('time')[1])
assert(type(capacity) == "number", "capacity is not a number!") assert(type(quota) == "number", "quota is not a number!") assert(type(period) == "number", "period is not a number!") assert(type(quantity) == "number", "quantity is not a number!")
if (redis.call('exists', key) == 0) then redis.call('hmset', key, 'remain', capacity, 'timestamp', timestamp) else local remain = tonumber(redis.call('hget', key, 'remain')) local last_reset = tonumber(redis.call('hget', key, 'timestamp')) local delta_quota = math.floor(((timestamp - last_reset) / period) * quota) if (delta_quota > 0) then remain = remain + delta_quota if (remain > capacity) then remain = capacity end redis.call('hmset', key, 'remain', remain, 'timestamp', timestamp) end end
redis.call('hmset', key, 'capacity', capacity, 'quota', quota, 'period', period);
local result = {} local remain = tonumber(redis.call('hget', key, 'remain')) if (remain < quantity) then result = {1, capacity, remain} else result = {0, capacity, remain - quantity} redis.call('hincrby', key, 'remain', -quantity) end
return result
|