Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to define functions in redis \ lua?

I'm using Node.js, and the 'redis-scripto' module, and I'm trying to define a function in Lua:

 var redis = require("redis");  
 var redisClient = redis.createClient("6379","127.0.0.1");   

 var Scripto = require('redis-scripto');
 var scriptManager = new Scripto(redisClient);
 var scripts = {'add_script':'function add(i,j) return (i+j) end add(i,j)'};

 scriptManager.load(scripts);
 scriptManager.run('add_script', [], [1,1], function(err, result){
                    console.log(err || result);
 });

so I'm getting this error:

[Error: ERR Error running script (call to .... @enable_strict_lua:7: user_script:1: Script attempted to create global variable 'add']

so I've found that it's a protection, as explained in this thread:

"The doc-string of scriptingEnableGlobalsProtection indicates that intent is to notify script authors of common mistake (not using local)."

but I still didn't understand - where is this scripting.c ? and the solution of changing global tables seems risky to me.

Is there no simple way of setting functions to redis - using lua ?

like image 634
Aviram Netanel Avatar asked Jan 21 '14 10:01

Aviram Netanel


People also ask

Does Redis use Lua?

Redis lets users upload and execute Lua scripts on the server. Scripts can employ programmatic control structures and use most of the commands while executing to access the database. Because scripts execute in the server, reading and writing data from scripts is very efficient.

What are Redis functions?

Redis functions are an evolutionary step from ephemeral scripting. Functions provide the same core functionality as scripts but are first-class software artifacts of the database. Redis manages functions as an integral part of the database and ensures their availability via data persistence and replication.

What is Redis Evalsha?

Redis EVALSHA command evaluates a script cached on the server side by its SHA1 digest. Scripts are cached on the server side using the SCRIPT LOAD command. The command is otherwise identical to EVAL.


2 Answers

It looks like the script runner is running your code in a function. So when you create function add(), it thinks you're doing it inside a function by accident. It'll also, likely, have a similar issue with the arguments to the call to add(i,j). If this is correct then this should work:

local function add(i,j) return (i+j) end return add(1,1)

and if THAT works then hopefully this will too with your arguments passed from the js:

local function add(i,j) return (i+j) end return add(...)
like image 189
Alex Avatar answered Oct 10 '22 08:10

Alex


You have to assign an anonymous function to a variable (using local).

local just_return_it = function(value) 
    return value
end 

--// result contains the string "hello world"
local result = just_return_it("hello world")

Alternately, you can create a table and add functions as fields on the table. This allows a more object oriented style.

local obj = {}

function obj.name()
    return "my name is Tom"
end

--// result contains "my name is Tom" 
local result = obj.name()

Redis requires this to prevent access to the global scope. The entire scripting mechanism is designed to keep persistence out of the scripting layer. Allowing things in the global scope would create an easy way to subvert this, making it much more difficult to track and manage state on the server.

Note: this means you'll have to add the same functions to every script that uses them. They aren't persistent on the server.

like image 31
Waylon Flinn Avatar answered Oct 10 '22 07:10

Waylon Flinn