scripting with mruby #848

Closed
wants to merge 34 commits into
from

Conversation

Projects
None yet
3 participants

We have created a command REVAL to use mruby for scripting of Redis.

mruby is the lightweight implementation of the Ruby language complying to (part of) the ISO standard.
Ruby is good at processing strings, arrays, hashes, etc. with its pretty designed libraries.
With mruby, we can do complex data operations in Redis with simple scripts.

How do you think about this idea?
As this patch is still rough cutting, some works will be needed to fit with Redis.
(For example REVALSHA is not implemented. Not implemented features are listed later.)

If your feel positive about implementing scripting languages in Redis other than Lua, we would like to consider supporting JavaScript with v8.
JavaScript runs on both client-side and server-side.
If Redis supports JavaScript, we can write everything in JavaScript.

The usage of REVAL is as follows:


REVAL script numkeys key [key ...] arg [arg …]

Features

Run mruby in the context of Redis server.

> reval "[KEYS[0],KEYS[1],ARGV[0],ARGV[1]]" 2 key1 key2 first second
1) "key1"
2) "key2"
3) "first"
4) "second"

Call Redis commands from a mruby script. (same as EVAL command)

> reval "REDIS.call('set','foo','bar')" 0
OK

Conversion between mruby and Redis data types

Redis to mruby conversion table.

  • Redis integer reply -> mruby Integer
  • Redis bulk reply -> mruby String
  • Redis multi bulk reply -> mruby Array
  • Redis error reply -> mruby Exception
  • Redis Nil bulk reply and Nil multi bulk reply -> mruby nil

mruby to Redis conversion table.

  • mruby Integer -> Redis integer reply (the number is converted into an integer)
  • mruby String -> Redis bulk reply
  • mruby Array -> Redis multi bulk reply (truncated to the first nil inside the mruby array if any)
  • mruby Hash with a single ok key -> Redis status reply
  • mruby Hash with a single err key -> Redis error reply
  • mruby Error -> Redis error reply
  • mruby boolean false -> Redis Nil bulk reply
  • mruby boolean true -> Redis integer reply with value of 1.

(examples)

> reval "10" 0
(integer) 10

> reval "[1, 2, [3, 'Hello World!']]" 0
1) (integer) 1
2) (integer) 2
3) 1) (integer) 3
   2) "Hello World!"

> reval "REDIS.call('get', 'foo')" 0
"bar"

Not implemented yet

  • REVALSHA
  • REDIS.log
  • script timeout

tricknotes added some commits Nov 22, 2012

@tricknotes tricknotes Add reval command interface 2bccf4f
@tricknotes tricknotes Compile with mruby d213cbe
@tricknotes tricknotes Disable stdio for mruby 7cbd470
@tricknotes tricknotes Evaluate first argument with mruby a6a5b4a
@tricknotes tricknotes Support type cast
- String
- Integer
- Array
440143f
@tricknotes tricknotes Handle mruby error a7dcd73
@tricknotes tricknotes Handle mruby nil 9d0a842
@tricknotes tricknotes Handle mruby hash 05470c5
@tricknotes tricknotes Define ARGV bd3b750
@tricknotes tricknotes Define KEYS c0f52a3
@tricknotes tricknotes Set constants of ARGV 2b1c6f7
@tricknotes tricknotes Add check for argc c14acfc
@tricknotes tricknotes Handle syntax error
For more details,
see `showcallinfo(mrb_state *mrb)` at `deps/mruby/tools/mruby/mruby.c`.
aef385b
@tricknotes tricknotes Add mruby object `REDIS` for redis interface ca474a4
@tricknotes tricknotes Parse redis object to mruby object cd4c990
@tricknotes tricknotes Return error when `REDIS.call` called with no argument d1d1f0e
@tricknotes tricknotes Update src/Makefile.dep
exec: `make dep`
e0188b7
@tricknotes tricknotes Check argument for redis command
- Wrong number of args
- Unknown command
f631e61
@tricknotes tricknotes Extract error handling 795a9ec
@tricknotes tricknotes Apply `zfree` 4ec09b8
@tricknotes tricknotes Deny command that is not allowed from scripts a53642b
@tricknotes tricknotes Check argument type 32b9a53
@tricknotes tricknotes Return error if mruby object is recursive 4463464
@tricknotes tricknotes Support mruby boolean as a redis type
- mruby true  -> redis (integer) 1
- mruby false -> redis (nil)

This spec is followed by `eval` command.
7536ad6
@tricknotes tricknotes Add tests about mruby 2d371d4
@tricknotes tricknotes Add test about type conversion (redis -> mruby) 386fa8e
@tricknotes tricknotes Skip cleanup when argument isn't given 445d05a
@tricknotes tricknotes Add test about `REDIS.call` in mruby e00cbdc
@tricknotes tricknotes Add test about mruby error f6afde1
@tricknotes tricknotes Support redis status in mruby 4a09195
@tricknotes tricknotes Add test about recursive mruby object 5a3aae7
@tricknotes tricknotes Support mruby float as a redis integer 9edc859
@tricknotes tricknotes Stop force string
unhandled value should be returned nil
5f6963c
@tricknotes tricknotes Add mruby script function `REDIS.pcall` a5851f6

This is an awesome idea 👍

Owner

antirez commented May 7, 2013

Hello, thanks for your great effort, but as repeated may times in the past, the scripting will be limited to a single language: Lua. Redis lua scripts are not at the level of complexity where really a language should be different from the other, given that we are talking of similar late-binding very dynamic languages. So adding support for other languages would result in zero practical improvement and great complexity added. Thanks anyway!

antirez closed this May 7, 2013

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment