shavaluator
This library provides a convenient wrapper for sending Lua scripts to a Redis server via EVALSHA
.
What is EVALSHA?
EVALSHA
allows you to send Lua scripts to a Redis server by sending the SHA-1 hashes instead of actual script content. As long as the body of your script was previously sent to Redis via EVAL
or SCRIPT LOAD
, you can use EVALSHA
to avoid the overhead of sending your entire Lua script over the network.
A Shavaluator object wraps a Redis client for executing Lua scripts. When executing Lua scripts, a shavaluator will always attempt EVALSHA
first, falling back on EVAL
if the script has not yet been cached by the Redis server.
Example
require 'redis'
require 'shavaluator'
# 1. Initialize a shavaluator with a Redis client
redis = Redis.new(:host => '127.0.0.1', :port => 6379)
shavaluator = Shavaluator.new(:redis => redis)
# 2. Add a series of named Lua scripts to the shavaluator.
shavaluator.add(
:delequal => """
if redis.call('GET', KEYS[1]) == ARGV[1] then
return redis.call('DEL', KEYS[i])
end
return 0
"""
)
# 3. The 'delequal' script is now added to the shavaluator and bound
# as a method. When you call this, the shavaluator will first attempt
# an EVALSHA, and fall back onto EVAL.
shavaluator.delequal :keys => ['key'], :argv => ['val']
Adding scripts
Before you can run Lua scripts, you should give each one a name and add them to a shavaluator.
scripts = {
:delequal => """
if redis.call('GET', KEYS[1]) == ARGV[1] then
return redis.call('DEL', KEYS[i])
end
return 0
""",
:zmembers => """
local key = KEYS[1]
local results = {}
if redis.call('ZCARD', key) == 0 then
return {}
end
for i = 1, #ARGV, 1 do
local memberName = ARGV[i]
if redis.call('ZSCORE', key, memberName) then
table.insert(results, memberName)
end
end
return results
""",
}
shavaluator.add scripts
Adding a script does two things by default: it generates the SHA-1 of the script body, and binds the script name as a method on the shavaluator object. It does not perform any network operations, such as sending SCRIPT LOAD
to the Redis server.
Executing scripts
By default, adding a script to a shavaluator will bind each script as a method on the shavaluator object. These methods preserve redis-rb's calling convention for Lua scripts, where keys and script arguments are either passed via a hash, or as a pair of arrays.
-
hash:
shavaluator.your_script :keys => ['key1', 'key2'], :argv => ['arg1', 'arg2']
-
array pair:
shavaluator.your_script ['key1', 'key2'], ['arg1', 'arg2']
If you don't like the auto-binding interface, you can use the exec
function, which takes the name of a script.
shavaluator.exec 'your_script', :keys => ['key1', 'key2'], :argv => ['arg1', 'arg2']
Class reference
new(opts)
Creates a new Shavaluator object.
Options:
-
:redis
: (required) an instance of a redis-rb client that the Shavaluator will use to connect to a Redis server.
add(scripts, opts = {})
Adds Lua scripts to the shavaluator. scripts is a key/value object, mapping script names to script bodies.
Options:
-
:bind
: (defaults totrue
) new methods will be created for each script.
exec(script_name, params...)
Executes the script corresponding to the provided script_name
. Script parameters can be passed in two different ways. See Executing scripts for usage examples.