Class: Prop::IntervalStrategy
- Inherits:
-
Object
- Object
- Prop::IntervalStrategy
- Defined in:
- lib/prop/interval_strategy.rb
Class Method Summary collapse
-
.build(options) ⇒ Object
Builds the expiring cache key.
- .compare_threshold?(counter, operator, options) ⇒ Boolean
- .counter(cache_key, options) ⇒ Object
- .first_throttled?(counter, options) ⇒ Boolean
- .increment(cache_key, options) ⇒ Object
- .reset(cache_key) ⇒ Object
- .threshold_reached(options) ⇒ Object
- .validate_options!(options) ⇒ Object
- .zero_counter ⇒ Object
Class Method Details
.build(options) ⇒ Object
Builds the expiring cache key
37 38 39 40 41 42 43 44 45 46 |
# File 'lib/prop/interval_strategy.rb', line 37 def build() key = .fetch(:key) handle = .fetch(:handle) interval = .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) ⇒ Boolean
27 28 29 30 |
# File 'lib/prop/interval_strategy.rb', line 27 def compare_threshold?(counter, operator, ) return false unless counter counter.send operator, .fetch(:threshold) end |
.counter(cache_key, options) ⇒ Object
12 13 14 |
# File 'lib/prop/interval_strategy.rb', line 12 def counter(cache_key, ) Prop::Limiter.cache.read(cache_key).to_i end |
.first_throttled?(counter, options) ⇒ Boolean
32 33 34 |
# File 'lib/prop/interval_strategy.rb', line 32 def first_throttled?(counter, ) (counter - .fetch(:increment, 1)) <= .fetch(:threshold) end |
.increment(cache_key, options) ⇒ Object
16 17 18 19 20 21 |
# File 'lib/prop/interval_strategy.rb', line 16 def increment(cache_key, ) increment = .fetch(:increment, 1) raise ArgumentError, "Increment must be a Fixnum, was #{increment.class}" unless increment.is_a?(Fixnum) cache = Prop::Limiter.cache cache.increment(cache_key, increment) || (cache.write(cache_key, increment, raw: true) && increment) # WARNING: potential race condition end |
.reset(cache_key) ⇒ Object
23 24 25 |
# File 'lib/prop/interval_strategy.rb', line 23 def reset(cache_key) Prop::Limiter.cache.write(cache_key, zero_counter, raw: true) end |
.threshold_reached(options) ⇒ Object
48 49 50 51 52 |
# File 'lib/prop/interval_strategy.rb', line 48 def threshold_reached() threshold = .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) ⇒ Object
54 55 56 57 58 59 60 61 |
# File 'lib/prop/interval_strategy.rb', line 54 def () validate_positive_integer([:threshold], :threshold) validate_positive_integer([:interval], :interval) if .key?(:increment) raise ArgumentError.new(":increment must be zero or a positive Integer") if ![:increment].is_a?(Fixnum) || [:increment] < 0 end end |
.zero_counter ⇒ Object
8 9 10 |
# File 'lib/prop/interval_strategy.rb', line 8 def zero_counter 0 end |