class Praroter::FillyBucket::Creator

Constants

LUA_SCRIPT_CODE
LUA_SCRIPT_HASH

Public Class Methods

new(redis:) click to toggle source
# File lib/praroter/filly_bucket/creator.rb, line 8
def initialize(redis:)
  @redis = redis.respond_to?(:with) ? redis : NullPool.new(redis)
end

Public Instance Methods

run_lua_bucket_script(bucket, amount) click to toggle source
# File lib/praroter/filly_bucket/creator.rb, line 16
def run_lua_bucket_script(bucket, amount)
  @redis.with do |r|
    begin
      # The script returns a tuple of "whole tokens, microtokens"
      # to be able to smuggle the float across (similar to Redis TIME command)
      new_bucket_level, bucket_capacity, fill_rate, scoop = r.evalsha(
        LUA_SCRIPT_HASH,
        keys: [bucket.level_key, bucket.last_updated_key],
        argv: [bucket.capacity, bucket.fill_rate, amount]
      )
      BucketState.new(new_bucket_level, bucket_capacity, fill_rate, scoop)
    rescue Redis::CommandError => e
      if e.message.include? "NOSCRIPT"
        # The Redis server has never seen this script before. Needs to run only once in the entire lifetime
        # of the Redis server, until the script changes - in which case it will be loaded under a different SHA
        r.script(:load, LUA_SCRIPT_CODE)
        retry
      else
        raise e
      end
    end
  end
end
setup_bucket(key:, fill_rate:, capacity:) click to toggle source
# File lib/praroter/filly_bucket/creator.rb, line 12
def setup_bucket(key:, fill_rate:, capacity:)
  Praroter::FillyBucket::Bucket.new(key, fill_rate, capacity, self)
end