Class: Berater::RateLimiter
- Defined in:
- lib/berater/rate_limiter.rb
Constant Summary collapse
- LUA_SCRIPT =
Berater::LuaScript(<<~LUA local key = KEYS[1] local ts = tonumber(ARGV[1]) local capacity = tonumber(ARGV[2]) local interval_msec = tonumber(ARGV[3]) local cost = tonumber(ARGV[4]) local allowed -- whether lock was acquired local count -- capacity being utilized local msec_per_drip = interval_msec / capacity local state = redis.call('GET', key) if state then local last_ts -- timestamp of last update count, last_ts = string.match(state, '([%d.]+);(%w+)') count = tonumber(count) last_ts = tonumber(last_ts, 16) -- adjust for time passing, guarding against clock skew if ts > last_ts then local drips = math.floor((ts - last_ts) / msec_per_drip) count = math.max(0, count - drips) else ts = last_ts end else count = 0 end if cost == 0 then -- just checking count allowed = true else allowed = (count + cost) <= capacity if allowed then count = count + cost -- time for bucket to empty, in milliseconds local ttl = math.ceil(count * msec_per_drip) ttl = ttl + 100 -- margin of error, for clock skew -- update count and last_ts, with expiration state = string.format('%f;%X', count, ts) redis.call('SET', key, state, 'PX', ttl) end end return { tostring(count), allowed } LUA )
Constants inherited from Limiter
Instance Attribute Summary
Attributes inherited from Limiter
Instance Method Summary collapse
-
#initialize(key, capacity, interval, **opts) ⇒ RateLimiter
constructor
A new instance of RateLimiter.
- #interval ⇒ Object
- #to_s ⇒ Object
Methods inherited from Limiter
#==, cache_key, #limit, new, #redis, #utilization
Constructor Details
#initialize(key, capacity, interval, **opts) ⇒ RateLimiter
Returns a new instance of RateLimiter.
4 5 6 7 |
# File 'lib/berater/rate_limiter.rb', line 4 def initialize(key, capacity, interval, **opts) super(key, capacity, interval, **opts) self.interval = interval end |
Instance Method Details
#interval ⇒ Object
9 10 11 |
# File 'lib/berater/rate_limiter.rb', line 9 def interval args[0] end |
#to_s ⇒ Object
90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/berater/rate_limiter.rb', line 90 def to_s msg = if interval.is_a? Numeric if interval == 1 "every second" else "every #{interval} seconds" end else "per #{interval}" end "#<#{self.class}(#{key}: #{capacity} #{msg})>" end |