Sha256: 634dcbcdbda0ba4eb4f44c0c39ce98b49ede7469dbfec3be3e986bc0fb02917a
Contents?: true
Size: 1.5 KB
Versions: 1
Compression:
Stored size: 1.5 KB
Contents
require "digest" require "prorate" module Millrace class RateLimit def initialize(name:, rate:, window:, penalty: 0, redis_config: nil) @name = name @rate = rate @window = window @penalty = penalty @redis_config = redis_config end attr_reader :name, :rate, :window def before(controller) bucket = get_bucket(controller.request.remote_ip) level = record_request(bucket) return unless level > threshold if level - 1 < threshold level = bucket.fillup(penalty).level end raise RateLimited.new(limit_name: name, retry_after: retry_after(level)) end private def retry_after(level) ((level - threshold) / rate).to_i end def record_request(bucket) bucket.fillup(1).level end def get_bucket(ip) Prorate::LeakyBucket.new( redis: redis, redis_key_prefix: key(ip), leak_rate: rate, bucket_capacity: capacity, ) end def key(ip) "millrace.#{name}.#{Digest::SHA1.hexdigest(ip)}" end def capacity (threshold * 2) + penalty end def threshold window * rate end def penalty @penalty * rate end def redis_config @redis_config || { url: ENV.fetch("MILLRACE_REDIS_URL", nil) }.compact end def redis Thread.current["millrace_#{name}_redis"] ||= Redis.new(redis_config) end end end
Version data entries
1 entries across 1 versions & 1 rubygems
Version | Path |
---|---|
millrace-0.1.0 | lib/millrace/rate_limit.rb |