Class: Prorate::LeakyBucket
- Inherits:
-
Object
- Object
- Prorate::LeakyBucket
- Defined in:
- lib/prorate/leaky_bucket.rb
Overview
This offers just the leaky bucket implementation with fill control, but without the timed lock. It does not raise any exceptions, it just tracks the state of a leaky bucket in Redis.
Important differences from the more full-featured Throttle class are:
-
No logging (as most meaningful code lives in Lua anyway)
-
No timed block - if you need to keep track of timed blocking it can be done externally
-
Leak rate is specified directly in tokens per second, instead of specifying the block period.
-
The bucket level is stored and returned as a Float which allows for finer-grained measurement, but more importantly - makes testing from the outside easier.
It does have a few downsides compared to the Throttle though
-
Bucket is only full momentarily. On subsequent calls some tokens will leak already, so you either need to do delta checks on the value or rely on putting the token into the bucket.
Defined Under Namespace
Classes: BucketState
Constant Summary collapse
- LUA_SCRIPT_CODE =
File.read(File.join(__dir__, "leaky_bucket.lua"))
- LUA_SCRIPT_HASH =
Digest::SHA1.hexdigest(LUA_SCRIPT_CODE)
Instance Method Summary collapse
-
#fillup(n_tokens) ⇒ BucketState
Places ‘n` tokens in the bucket.
-
#initialize(redis_key_prefix:, leak_rate:, redis:, bucket_capacity:) ⇒ LeakyBucket
constructor
Creates a new LeakyBucket.
-
#last_updated_key ⇒ String
Returns the Redis key under which the last updated time of the bucket gets stored.
-
#leaky_bucket_key ⇒ String
Returns the Redis key for the leaky bucket itself Note that the key is not guaranteed to contain a value if the bucket has not been filled up recently.
-
#state ⇒ BucketState
Returns the current state of the bucket, containing the level and whether the bucket is full.
Constructor Details
#initialize(redis_key_prefix:, leak_rate:, redis:, bucket_capacity:) ⇒ LeakyBucket
Creates a new LeakyBucket. The object controls 2 keys in Redis: one for the last access time, and one for the contents of the key.
71 72 73 74 75 76 |
# File 'lib/prorate/leaky_bucket.rb', line 71 def initialize(redis_key_prefix:, leak_rate:, redis:, bucket_capacity:) @redis_key_prefix = redis_key_prefix @redis = redis.respond_to?(:with) ? redis : NullPool.new(redis) @leak_rate = leak_rate.to_f @capacity = bucket_capacity.to_f end |
Instance Method Details
#fillup(n_tokens) ⇒ BucketState
Places ‘n` tokens in the bucket.
81 82 83 |
# File 'lib/prorate/leaky_bucket.rb', line 81 def fillup(n_tokens) run_lua_bucket_script(n_tokens.to_f) end |
#last_updated_key ⇒ String
Returns the Redis key under which the last updated time of the bucket gets stored. Note that the key is not guaranteed to contain a value if the bucket has not been filled up recently.
106 107 108 |
# File 'lib/prorate/leaky_bucket.rb', line 106 def last_updated_key "#{@redis_key_prefix}.leaky_bucket.last_updated" end |
#leaky_bucket_key ⇒ String
Returns the Redis key for the leaky bucket itself Note that the key is not guaranteed to contain a value if the bucket has not been filled up recently.
97 98 99 |
# File 'lib/prorate/leaky_bucket.rb', line 97 def leaky_bucket_key "#{@redis_key_prefix}.leaky_bucket.bucket_level" end |
#state ⇒ BucketState
Returns the current state of the bucket, containing the level and whether the bucket is full
88 89 90 |
# File 'lib/prorate/leaky_bucket.rb', line 88 def state run_lua_bucket_script(0) end |