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
- .decrement(cache_key, amount, options = {}) ⇒ Object
- .first_throttled?(counter, options) ⇒ Boolean
-
.increment(cache_key, amount, options = {}) ⇒ Object
options argument is kept for api consistency for all strategies.
- .reset(cache_key, options = {}) ⇒ Object
- .threshold_reached(options) ⇒ Object
- .validate_options!(options) ⇒ Object
- .zero_counter ⇒ Object
Class Method Details
.build(options) ⇒ Object
Builds the expiring cache key
41 42 43 44 45 46 47 48 49 50 |
# File 'lib/prop/interval_strategy.rb', line 41 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
31 32 33 34 |
# File 'lib/prop/interval_strategy.rb', line 31 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, ) cache.read(cache_key, raw: true).to_i end |
.decrement(cache_key, amount, options = {}) ⇒ Object
22 23 24 25 |
# File 'lib/prop/interval_strategy.rb', line 22 def decrement(cache_key, amount, = {}) raise ArgumentError, "Change amount must be a Integer, was #{amount.class}" unless amount.is_a?(Integer) cache.decrement(cache_key, amount, expires_in: .fetch(:interval, nil)) || (cache.write(cache_key, 0, raw: true, expires_in: .fetch(:interval, nil)) && 0) # WARNING: potential race condition end |
.first_throttled?(counter, options) ⇒ Boolean
36 37 38 |
# File 'lib/prop/interval_strategy.rb', line 36 def first_throttled?(counter, ) (counter - .fetch(:increment, 1)) <= .fetch(:threshold) end |
.increment(cache_key, amount, options = {}) ⇒ Object
options argument is kept for api consistency for all strategies
17 18 19 20 |
# File 'lib/prop/interval_strategy.rb', line 17 def increment(cache_key, amount, = {}) raise ArgumentError, "Change amount must be a Integer, was #{amount.class}" unless amount.is_a?(Integer) cache.increment(cache_key, amount, expires_in: .fetch(:interval, nil)) || (cache.write(cache_key, amount, raw: true, expires_in: .fetch(:interval, nil)) && amount) # WARNING: potential race condition end |
.reset(cache_key, options = {}) ⇒ Object
27 28 29 |
# File 'lib/prop/interval_strategy.rb', line 27 def reset(cache_key, = {}) cache.write(cache_key, zero_counter, raw: true, expires_in: .fetch(:interval, nil)) end |
.threshold_reached(options) ⇒ Object
52 53 54 55 56 |
# File 'lib/prop/interval_strategy.rb', line 52 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
58 59 60 61 62 63 64 65 66 |
# File 'lib/prop/interval_strategy.rb', line 58 def () validate_threshold([:threshold], :threshold) validate_interval([:interval], :interval) amount = [:increment] || [: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 ⇒ Object
8 9 10 |
# File 'lib/prop/interval_strategy.rb', line 8 def zero_counter 0 end |