2024-05-03 03:04:43 +00:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
class RateLimiter::InMemory < RateLimiter
|
|
|
|
attr_reader :list
|
|
|
|
|
|
|
|
def initialize
|
|
|
|
super
|
|
|
|
@list = {}
|
|
|
|
end
|
|
|
|
|
|
|
|
def get_global(name, ip)
|
|
|
|
list[global_key(name, ip)].try(:[], :count)
|
|
|
|
end
|
|
|
|
|
|
|
|
def get_route(name, domain, path, ip)
|
|
|
|
list[route_key(name, domain, path, ip)].try(:[], :count)
|
|
|
|
end
|
|
|
|
|
|
|
|
def get_global_ttl(name, ip)
|
|
|
|
list[global_key(name, ip)].try(:[], :expiry)
|
|
|
|
end
|
|
|
|
|
|
|
|
def get_route_ttl(name, domain, path, ip)
|
|
|
|
list[route_key(name, domain, path, ip)].try(:[], :expiry)
|
|
|
|
end
|
|
|
|
|
|
|
|
def consume_global(name, window, limit, ip)
|
|
|
|
consume(global_key(name, ip), window, limit)
|
|
|
|
end
|
|
|
|
|
|
|
|
def consume_route(name, domain, path, window, limit, ip)
|
|
|
|
consume(route_key(name, domain, path, ip), window, limit)
|
|
|
|
end
|
|
|
|
|
|
|
|
def fix_infinite_expiry(_key, val, expiry)
|
|
|
|
# noop
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
def consume(key, window, limit)
|
2024-10-21 06:32:17 +00:00
|
|
|
list[key] || { count: 0, expiry: nil } => { count:, expiry: }
|
2024-05-03 03:04:43 +00:00
|
|
|
|
|
|
|
if expiry && expiry < Time.now.to_i
|
|
|
|
list.delete(key)
|
|
|
|
count = expiry = nil
|
|
|
|
end
|
|
|
|
|
|
|
|
return count + 1 if count && count < limit
|
|
|
|
|
|
|
|
count = (count || 0) + 1
|
|
|
|
expiry ||= Time.now.to_i + window
|
|
|
|
list[key] = { count: count, expiry: expiry }
|
|
|
|
count
|
|
|
|
end
|
|
|
|
end
|