class Prop::IntervalStrategy
Public Class Methods
build(options)
click to toggle source
Builds the expiring cache key
# File lib/prop/interval_strategy.rb, line 41 def build(options) key = options.fetch(:key) handle = options.fetch(:handle) interval = options.fetch(:interval) window = (Time.now.to_i / interval) cache_key = Prop::Key.normalize([ handle, key, window ]) "prop/v2/#{Digest::MD5.hexdigest(cache_key)}" end
compare_threshold?(counter, operator, options)
click to toggle source
# File lib/prop/interval_strategy.rb, line 31 def compare_threshold?(counter, operator, options) return false unless counter counter.send operator, options.fetch(:threshold) end
counter(cache_key, options)
click to toggle source
# File lib/prop/interval_strategy.rb, line 12 def counter(cache_key, options) cache.read(cache_key, raw: true).to_i end
decrement(cache_key, amount, options = {})
click to toggle source
# File lib/prop/interval_strategy.rb, line 22 def decrement(cache_key, amount, options = {}) raise ArgumentError, "Change amount must be a Integer, was #{amount.class}" unless amount.is_a?(Integer) cache.decrement(cache_key, amount, expires_in: options.fetch(:interval, nil)) || (cache.write(cache_key, 0, raw: true, expires_in: options.fetch(:interval, nil)) && 0) # WARNING: potential race condition end
first_throttled?(counter, options)
click to toggle source
# File lib/prop/interval_strategy.rb, line 36 def first_throttled?(counter, options) (counter - options.fetch(:increment, 1)) <= options.fetch(:threshold) end
increment(cache_key, amount, options = {})
click to toggle source
options argument is kept for api consistency for all strategies
# File lib/prop/interval_strategy.rb, line 17 def increment(cache_key, amount, options = {}) raise ArgumentError, "Change amount must be a Integer, was #{amount.class}" unless amount.is_a?(Integer) cache.increment(cache_key, amount, expires_in: options.fetch(:interval, nil)) || (cache.write(cache_key, amount, raw: true, expires_in: options.fetch(:interval, nil)) && amount) # WARNING: potential race condition end
reset(cache_key, options = {})
click to toggle source
# File lib/prop/interval_strategy.rb, line 27 def reset(cache_key, options = {}) cache.write(cache_key, zero_counter, raw: true, expires_in: options.fetch(:interval, nil)) end
threshold_reached(options)
click to toggle source
# File lib/prop/interval_strategy.rb, line 52 def threshold_reached(options) threshold = options.fetch(:threshold) "#{options[:handle]} threshold of #{threshold} tries per #{options[:interval]}s exceeded for key #{options[:key].inspect}, hash #{options[:cache_key]}" end
validate_options!(options)
click to toggle source
# File lib/prop/interval_strategy.rb, line 58 def validate_options!(options) validate_threshold(options[:threshold], :threshold) validate_interval(options[:interval], :interval) amount = options[:increment] || options[:decrement] if amount raise ArgumentError.new(":increment or :decrement must be zero or a positive Integer") if !amount.is_a?(Integer) || amount < 0 end end
zero_counter()
click to toggle source
# File lib/prop/interval_strategy.rb, line 8 def zero_counter 0 end
Private Class Methods
cache()
click to toggle source
# File lib/prop/interval_strategy.rb, line 78 def cache Prop::Limiter.cache end
validate_interval(option, key)
click to toggle source
# File lib/prop/interval_strategy.rb, line 74 def validate_interval(option, key) raise ArgumentError.new("#{key.inspect} must be a positive Integer") if !option.is_a?(Integer) || option <= 0 end
validate_threshold(option, key)
click to toggle source
# File lib/prop/interval_strategy.rb, line 70 def validate_threshold(option, key) raise ArgumentError.new("#{key.inspect} must be a non-negative Integer") if !option.is_a?(Integer) || option < 0 end