class LeakyBucket::Throttler
Attributes
cache[RW]
Public Class Methods
throttle(ip, threshold: 100, interval: 3600, burst: 10)
click to toggle source
# File lib/leaky_bucket/throttler.rb, line 16 def throttle(ip, threshold: 100, interval: 3600, burst: 10) bucket = LeakyBucket.cache.read(ip) || new_counter #leak proper number of requests since last request time. bucket = leak(bucket, threshold, interval) if bucket[:current_load] > burst raise LeakyBucket::TooManyRequests.new((interval/threshold) - (Time.now.to_i - bucket[:last_request_made_at])) end increment(ip, bucket) end
Private Class Methods
increment(ip, bucket)
click to toggle source
# File lib/leaky_bucket/throttler.rb, line 41 def increment(ip, bucket) bucket[:current_load] += 1 bucket[:last_request_made_at] = Time.now.to_i LeakyBucket.cache.write(ip, bucket) end
leak(bucket, threshold, interval)
click to toggle source
# File lib/leaky_bucket/throttler.rb, line 31 def leak(bucket, threshold, interval) now = Time.now.to_i #the bucket leaks 100 requests/hour by default ~= 1.6 request/minute leak_rate = interval / threshold leak_amount = (now - bucket[:last_request_made_at]) / leak_rate #decrement the bucket load, or empty it if it's been a long enough time for it to leak everything bucket[:current_load] = [bucket[:current_load] - leak_amount, 0].max bucket end
new_counter()
click to toggle source
used as a cache key for the first api request from this IP address
# File lib/leaky_bucket/throttler.rb, line 48 def new_counter { current_load: 0, last_request_made_at: 0 } end