Class: Prop::LeakyBucketStrategy
- Inherits:
-
Object
- Object
- Prop::LeakyBucketStrategy
- Defined in:
- lib/prop/leaky_bucket_strategy.rb
Class Method Summary collapse
- .build(options) ⇒ Object
- .compare_threshold?(counter, operator, options) ⇒ Boolean
- .counter(cache_key, options) ⇒ Object
-
.increment(cache_key, options) ⇒ Object
WARNING: race condition this increment is not atomic, so it might miss counts when used frequently.
- .reset(cache_key) ⇒ Object
- .threshold_reached(options) ⇒ Object
- .validate_options!(options) ⇒ Object
Class Method Details
.build(options) ⇒ Object
36 37 38 39 40 41 42 43 |
# File 'lib/prop/leaky_bucket_strategy.rb', line 36 def build() key = .fetch(:key) handle = .fetch(:handle) cache_key = Prop::Key.normalize([ handle, key ]) "prop/leaky_bucket/#{Digest::MD5.hexdigest(cache_key)}" end |
.compare_threshold?(counter, operator, options) ⇒ Boolean
32 33 34 |
# File 'lib/prop/leaky_bucket_strategy.rb', line 32 def compare_threshold?(counter, operator, ) counter.fetch(:bucket).to_i.send operator, .fetch(:burst_rate) end |
.counter(cache_key, options) ⇒ Object
9 10 11 12 13 14 15 16 17 |
# File 'lib/prop/leaky_bucket_strategy.rb', line 9 def counter(cache_key, ) bucket = Prop::Limiter.cache.read(cache_key) || default_bucket now = Time.now.to_i leak_amount = (now - bucket.fetch(:last_updated)) / .fetch(:interval) * .fetch(:threshold) bucket[:bucket] = [bucket.fetch(:bucket) - leak_amount, 0].max bucket[:last_updated] = now bucket end |
.increment(cache_key, options) ⇒ Object
WARNING: race condition this increment is not atomic, so it might miss counts when used frequently
21 22 23 24 25 26 |
# File 'lib/prop/leaky_bucket_strategy.rb', line 21 def increment(cache_key, ) counter = counter(cache_key, ) counter[:bucket] += .fetch(:increment, 1) Prop::Limiter.cache.write(cache_key, counter) counter end |
.reset(cache_key) ⇒ Object
28 29 30 |
# File 'lib/prop/leaky_bucket_strategy.rb', line 28 def reset(cache_key) Prop::Limiter.cache.write(cache_key, default_bucket) end |
.threshold_reached(options) ⇒ Object
45 46 47 48 49 50 |
# File 'lib/prop/leaky_bucket_strategy.rb', line 45 def threshold_reached() burst_rate = .fetch(:burst_rate) threshold = .fetch(:threshold) "#{[:handle]} threshold of #{threshold} tries per #{[:interval]}s and burst rate #{burst_rate} tries exceeded for key #{[:key].inspect}, hash #{[:cache_key]}" end |
.validate_options!(options) ⇒ Object
52 53 54 55 56 57 58 |
# File 'lib/prop/leaky_bucket_strategy.rb', line 52 def () Prop::IntervalStrategy.() if ![:burst_rate].is_a?(Fixnum) || [:burst_rate] < [:threshold] raise ArgumentError.new(":burst_rate must be an Integer and larger than :threshold") end end |