Class: RedisThrottler::Base
- Inherits:
-
Object
- Object
- RedisThrottler::Base
- Defined in:
- lib/redis-throttler/base.rb
Instance Method Summary collapse
-
#add(subject, count = 1) ⇒ Integer
Increment counter for a given subject.
-
#count(subject, interval) ⇒ Integer
Returns the count for a given subject and interval.
-
#exceeded?(subject, options = {}) ⇒ Boolean
Check if the rate limit has been exceeded.
-
#exec_within_threshold(subject, options = {}) { ... } ⇒ Object
Execute a block once the rate limit is within bounds WARNING This will block the current thread until the rate limit is within bounds.
-
#initialize(key, options = {}) ⇒ RedisThrottler
constructor
Create a RedisThrottler object.
-
#within_bounds?(subject, options = {}) ⇒ Integer
Check if the rate limit is within bounds.
Constructor Details
#initialize(key, options = {}) ⇒ RedisThrottler
Create a RedisThrottler object.
14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
# File 'lib/redis-throttler/base.rb', line 14 def initialize(key, = {}) @key = key @bucket_span = [:bucket_span] || 600 @bucket_interval = [:bucket_interval] || 5 @bucket_expiry = [:bucket_expiry] || @bucket_span if @bucket_expiry > @bucket_span raise ArgumentError.new("Bucket expiry cannot be larger than the bucket span") end @bucket_count = (@bucket_span / @bucket_interval).round if @bucket_count < 3 raise ArgumentError.new("Cannot have less than 3 buckets") end @redis = [:redis] end |
Instance Method Details
#add(subject, count = 1) ⇒ Integer
Increment counter for a given subject.
35 36 37 38 39 40 41 42 43 44 |
# File 'lib/redis-throttler/base.rb', line 35 def add(subject, count = 1) bucket = get_bucket subject = "#{@key}:#{subject}" redis.pipelined do redis.hincrby(subject, bucket, count) redis.hdel(subject, (bucket + 1) % @bucket_count) redis.hdel(subject, (bucket + 2) % @bucket_count) redis.expire(subject, @bucket_expiry) end.first end |
#count(subject, interval) ⇒ Integer
Returns the count for a given subject and interval
52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/redis-throttler/base.rb', line 52 def count(subject, interval) bucket = get_bucket interval = [interval, @bucket_interval].max count = (interval / @bucket_interval).floor subject = "#{@key}:#{subject}" keys = (0..count - 1).map do |i| (bucket - i) % @bucket_count end redis.hmget(subject, *keys).inject(0) {|a, i| a + i.to_i} end |
#exceeded?(subject, options = {}) ⇒ Boolean
Check if the rate limit has been exceeded.
72 73 74 |
# File 'lib/redis-throttler/base.rb', line 72 def exceeded?(subject, = {}) count(subject, [:interval]) >= [:threshold] end |
#exec_within_threshold(subject, options = {}) { ... } ⇒ Object
Execute a block once the rate limit is within bounds WARNING This will block the current thread until the rate limit is within bounds.
101 102 103 104 105 106 107 108 |
# File 'lib/redis-throttler/base.rb', line 101 def exec_within_threshold(subject, = {}, &block) [:threshold] ||= 30 [:interval] ||= 30 while exceeded?(subject, ) sleep @bucket_interval end yield(self) end |
#within_bounds?(subject, options = {}) ⇒ Integer
Check if the rate limit is within bounds
84 85 86 |
# File 'lib/redis-throttler/base.rb', line 84 def within_bounds?(subject, = {}) !exceeded?(subject, ) end |