Websites/app/logical/rate_limiter/in_memory.rb
2024-05-02 22:04:43 -05:00

57 lines
1.2 KiB
Ruby

# 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)
(list[key] || { count: 0, expiry: nil }) => { count:, expiry: }
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