lib/rack/throttle/limiters/sliding_window.rb in improved-rack-throttle-0.7.1 vs lib/rack/throttle/limiters/sliding_window.rb in improved-rack-throttle-0.8.0
- old
+ new
@@ -1,11 +1,11 @@
module Rack; module Throttle
##
# This rate limiter strategy throttles the application with
# a sliding window (implemented as a leaky bucket). It operates
- # on second-level resolution. It takes :burst and :average
- # options, which correspond to the maximum size of a traffic
+ # on second-level resolution. It takes :burst and :average
+ # options, which correspond to the maximum size of a traffic
# burst, and the maximum allowed average traffic level.
class SlidingWindow < Limiter
##
# @param [#call] app
# @param [Hash{Symbol => Object}] options
@@ -16,22 +16,22 @@
options[:burst] ||= 5
options[:average] ||= 1
end
##
- # Returns `true` if the request conforms to the
+ # Returns `true` if the request conforms to the
# specified :average and :burst rules
#
# @param [Rack::Request] request
# @return [Boolean]
def allowed?(request)
t1 = request_start_time(request)
key = cache_key(request)
bucket = cache_get(key) rescue nil
bucket ||= LeakyBucket.new(options[:burst], options[:average])
bucket.maximum, bucket.outflow = options[:burst], options[:average]
- bucket.leak!
+ bucket.leak!
bucket.increment!
allowed = !bucket.full?
begin
cache_set(key, bucket)
allowed
@@ -42,10 +42,19 @@
# This prevents the Rack application blowing up merely due to a
# backend cache server (Memcached, Redis, etc.) being offline.
end
end
+ ##
+ # Returns the number of seconds before the client is allowed to retry an
+ # HTTP request.
+ #
+ # @return [Float]
+ def retry_after
+ @retry_after ||= (1.0 / options[:average].to_f)
+ end
+
###
# LeakyBucket is an internal class used to implement the
# SlidingWindow limiter strategy. It is a (slightly tweaked)
# implementation of the {http://en.wikipedia.org/wiki/Leaky_bucket
# Leaky Bucket Algorithm}.
@@ -65,10 +74,10 @@
t = Time.now
time = t - last_touched
loss = (outflow * time).to_f
if loss > 0
@count -= loss
- @last_touched = t
+ @last_touched = t
end
end
def increment!
@count = 0 if count < 0