shavaluator-js
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
Shavaluator = require('shavaluator')
var shavaluator = new Shavaluator(redis);
shavaluator.add({
delequal:
" \
if redis.call('GET', KEYS[1]) == ARGV[1] then \
return redis.call('DEL', KEYS[i]) \
end \
return 0 \
"
});
shavaluator.delequal({ keys: 'someKey', args: 'deleteMe' });
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 function property 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 top-level function on the shavaluator object. These functions preserve Redis's calling convention for Lua scripts, where key arguments are separated from normal arguments.
Shavaluator offers three overloaded function signatures:
1. keys/args hash
args = { keys: ['key1', 'key2'], args: ['arg1', 'arg2'] };
shavaluator.yourScript(args, function(err, result){
...
});
args = { keys: 'soleKey', args: 'soleArg' };
shavaluator.yourScript(args, function(err, result) {
...
});
2. Original EVAL/EVALSHA signature: keyCount, keys..., args...
shavaluator.yourScript(2, 'key1', 'key2', 'arg1', 'arg2', function(err, result) {
...
});
3. Original EVAL/EVALSHA signature, as array
args = [ 2, 'key1', 'key2', 'arg1', 'arg2' ];
shavaluator.yourScript(args, function(err, result) {
...
});
eval()
If you don't like the auto-binding interface, you can use the eval
function, which takes the name of a script.
args = { keys: ['key1', 'key2'], args: ['arg1', 'arg2'] }
shavaluator.eval('yourScript', args, function(err, result){
...
});
Class reference
constructor(redisClient, [options])
Available options:
autobind
Set this to false
if yo don't want the add
function to automatically bind script-calling functions to the shavaluator object. Defaults to true
.
add(scripts, [options])
Adds Lua scripts to the shavaluator. scripts
is a key/value object, mapping script names to script bodies.
Available options:
autobind
Overrides the autobind
option set in the constructor.
eval(scriptName, params..., [callback])
Executes the script named scriptName
. Script parameters can be passed in three different ways. See Executing scripts for usage examples.
The optional callback
parameter is standard asynchronous callback, taking two arguments:
- an error, which is null on success
- the script result