lib/prop/limiter.rb in prop-1.1.0 vs lib/prop/limiter.rb in prop-1.2.0
- old
+ new
@@ -1,8 +1,10 @@
require 'prop/rate_limited'
require 'prop/key'
require 'prop/options'
+require 'prop/interval_strategy'
+require 'prop/leaky_bucket_strategy'
module Prop
class Limiter
class << self
@@ -52,22 +54,21 @@
# (optional) a block of code that this throttle is guarding
#
# Returns true if the threshold for this handle has been reached, else returns false
def throttle(handle, key = nil, options = {})
options, cache_key = prepare(handle, key, options)
- counter = reader.call(cache_key).to_i
+ counter = @strategy.counter(cache_key, options)
unless disabled?
- if at_threshold?(counter, options[:threshold])
+ if @strategy.at_threshold?(counter, options)
unless before_throttle_callback.nil?
before_throttle_callback.call(handle, key, options[:threshold], options[:interval])
end
true
else
- increment = options.key?(:increment) ? options[:increment].to_i : 1
- writer.call(cache_key, counter + increment)
+ @strategy.increment(cache_key, options, counter)
yield if block_given?
false
end
@@ -88,67 +89,67 @@
if throttle(handle, key, options)
raise Prop::RateLimited.new(options.merge(:cache_key => cache_key, :handle => handle))
end
- block_given? ? yield : reader.call(cache_key).to_i
+ block_given? ? yield : @strategy.counter(cache_key, options)
end
# Public: Allows to query whether the given handle/key combination is currently throttled
#
# handle - the throttle identifier
# key - the associated key
#
# Returns true if a call to `throttle!` with same parameters would raise, otherwise false
def throttled?(handle, key = nil, options = {})
options, cache_key = prepare(handle, key, options)
- reader.call(cache_key).to_i >= options[:threshold]
+ counter = @strategy.counter(cache_key, options)
+ @strategy.at_threshold?(counter, options)
end
# Public: Resets a specific throttle
#
# handle - the throttle identifier
# key - the associated key
#
# Returns nothing
def reset(handle, key = nil, options = {})
options, cache_key = prepare(handle, key, options)
- writer.call(cache_key, 0)
+ @strategy.reset(cache_key)
end
# Public: Counts the number of times the given handle/key combination has been hit in the current window
#
# handle - the throttle identifier
# key - the associated key
#
# Returns a count of hits in the current window
def count(handle, key = nil, options = {})
options, cache_key = prepare(handle, key, options)
- reader.call(cache_key).to_i
+ @strategy.counter(cache_key, options)
end
alias :query :count
def handles
@handles ||= {}
end
alias :configurations :handles
private
- def at_threshold?(mark, threshold)
- mark >= threshold
- end
-
def disabled?
!!@disabled
end
def prepare(handle, key, params)
raise RuntimeError.new("No such handle configured: #{handle.inspect}") unless (handles || {}).key?(handle)
defaults = handles[handle]
options = Prop::Options.build(:key => key, :params => params, :defaults => defaults)
- cache_key = Prop::Key.build(:key => key, :handle => handle, :interval => options[:interval])
+
+ @strategy = options.fetch(:strategy)
+
+ cache_key = @strategy.build(:key => key, :handle => handle, :interval => options[:interval])
[ options, cache_key ]
end
end
end