class Brpoplpush::RedisScript::Client

Interface to dealing with .lua files

@author Mikael Henriksson <mikael@mhenrixon.com>

Attributes

config[R]

@!attribute [r] file_name

@return [String] The name of the file to execute
logger[R]

@!attribute [r] logger

@return [Logger] an instance of a logger
scripts[R]

@!attribute [r] scripts

@return [Scripts] the collection with loaded scripts

Public Class Methods

new(config) click to toggle source
# File lib/brpoplpush/redis_script/client.rb, line 24
def initialize(config)
  @config  = config
  @logger  = config.logger
  @scripts = Scripts.fetch(config.scripts_path)
end

Public Instance Methods

execute(script_name, conn, keys: [], argv: []) click to toggle source

Execute a lua script with the provided script_name

@note this method is recursive if we need to load a lua script

that wasn't previously loaded.

@param [Symbol] script_name the name of the script to execute @param [Redis] conn the redis connection to use for execution @param [Array<String>] keys script keys @param [Array<Object>] argv script arguments

@return value from script

# File lib/brpoplpush/redis_script/client.rb, line 43
def execute(script_name, conn, keys: [], argv: [])
  result, elapsed = timed do
    scripts.execute(script_name, conn, keys: keys, argv: argv)
  end

  logger.debug("Executed #{script_name}.lua in #{elapsed}ms")
  result
rescue ::Redis::CommandError => ex
  handle_error(script_name, conn, ex) do
    execute(script_name, conn, keys: keys, argv: argv)
  end
end

Private Instance Methods

handle_busy(conn) { || ... } click to toggle source
# File lib/brpoplpush/redis_script/client.rb, line 85
def handle_busy(conn)
  scripts.kill(conn)
rescue ::Redis::CommandError => ex
  logger.warn(ex)
ensure
  yield
end
handle_error(script_name, conn, ex) { || ... } click to toggle source

Handle errors to allow retrying errors that need retrying

@param [Redis::CommandError] ex exception to handle

@return [void]

@yieldreturn [void] yields back to the caller when NOSCRIPT is raised

# File lib/brpoplpush/redis_script/client.rb, line 66
def handle_error(script_name, conn, ex)
  case ex.message
  when /NOSCRIPT/
    handle_noscript(script_name) { return yield }
  when /BUSY/
    handle_busy(conn) { return yield }
  end

  raise unless LuaError.intercepts?(ex)

  script = scripts.fetch(script_name, conn)
  raise LuaError.new(ex, script)
end
handle_noscript(script_name) { || ... } click to toggle source
# File lib/brpoplpush/redis_script/client.rb, line 80
def handle_noscript(script_name)
  scripts.delete(script_name)
  yield
end