feature(redis): lua script words
authorRudi Grinberg <me@rgrinberg.com>
Sat, 17 Sep 2022 18:33:34 +0000 (12:33 -0600)
committerJohn Benediktsson <mrjbq7@gmail.com>
Sat, 17 Sep 2022 18:56:12 +0000 (11:56 -0700)
Add words to run/load/debug lua scripts

extra/redis/command-writer/command-writer-tests.factor
extra/redis/command-writer/command-writer.factor
extra/redis/redis-tests.factor
extra/redis/redis.factor

index cd4cddd08c599386ef25df4dabef9e8d80b57385..9edf1c458825d07a2b6991ffadfafb66254a05aa 100644 (file)
@@ -229,3 +229,17 @@ IN: redis.command-writer.tests
 { "*1\r\n$4\r\nINFO\r\n" } [ [ info ] with-string-writer ] unit-test
 
 { "*1\r\n$7\r\nMONITOR\r\n" } [ [ monitor ] with-string-writer ] unit-test
+
+! Lua
+
+{ "*3\r\n$6\r\nSCRIPT\r\n$4\r\nLOAD\r\n$8\r\nreturn 1\r\n" } [ [ "return 1" script-load ] with-string-writer ] unit-test
+
+{ "*3\r\n$6\r\nSCRIPT\r\n$6\r\nEXISTS\r\n$9\r\nfake-hash\r\n" } [ [ { "fake-hash" } script-exists ] with-string-writer ] unit-test
+
+{ "*2\r\n$6\r\nSCRIPT\r\n$5\r\nFLUSH\r\n" } [ [ script-flush ] with-string-writer ] unit-test
+
+{ "*2\r\n$6\r\nSCRIPT\r\n$4\r\nKILL\r\n" } [ [ script-kill ] with-string-writer ] unit-test
+
+{ "*6\r\n$4\r\nEVAL\r\n$36\r\nreturn { KEYS[1], KEYS[2], ARGV[1] }\r\n$1\r\n2\r\n$1\r\na\r\n$1\r\nb\r\n$3\r\n100\r\n" } [
+    [ "return { KEYS[1], KEYS[2], ARGV[1] }" { "a" "b" } { 100 } script-eval ] with-string-writer
+] unit-test
index af6ac6021c50fc85944f5c0260bd9c6b2cba3fb3..6657f64b0a5bffab56afafe7de1874912ac44aa3 100644 (file)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2009 Bruno Deferrari
 ! See http://factorcode.org/license.txt for BSD license.
 USING: arrays assocs formatting kernel math math.parser
-sequences strings ;
+sequences strings make ;
 IN: redis.command-writer
 
 <PRIVATE
@@ -23,6 +23,16 @@ M: sequence write-resp ( sequence -- )
     [ dup number? [ number>string ] when ] map
     write-resp ;
 
+: write-command-multi ( sequence command -- )
+    prepend
+    [ dup number? [ number>string ] when ] map
+    write-resp ;
+
+:: (script-eval) ( script keys args command -- )
+    [ script , keys length , keys % args % ] { } make
+    { command }
+    write-command-multi ;
+
 PRIVATE>
 
 ! Connection
@@ -122,3 +132,13 @@ PRIVATE>
 ! Remote server control
 : info ( -- ) { "INFO" } write-resp ;
 : monitor ( -- ) { "MONITOR" } write-resp ;
+
+! Lua
+: script-load ( script -- ) 1array { "SCRIPT" "LOAD" } write-command-multi ;
+: script-exists ( scripts -- ) { "SCRIPT" "EXISTS" } write-command-multi ;
+: script-flush ( -- ) { } { "SCRIPT" "FLUSH" } write-command-multi ;
+: script-kill ( -- ) { } { "SCRIPT" "KILL" } write-command-multi ;
+! YES | SYNC | NO
+: script-debug ( debug -- ) 1array { "SCRIPT" "DEBUG" } write-command-multi ;
+: script-evalsha ( sha keys args -- ) "EVALSHA" (script-eval) ;
+: script-eval ( script keys args -- ) "EVAL" (script-eval) ;
index 71cc81ae0b67eb26a7ecbb7f41afd962a6183fdb..249b93cb265001ec12b38b2e702fc92aebf33031 100644 (file)
@@ -66,3 +66,17 @@ IN: redis.tests
         [ "hello" redis-incr ] [ drop t ] recover
     ] with-redis-test
 ] unit-test
+
+{ "e0e1f9fabfc9d4800c877a703b823ac0578ff8db" } [
+    [ "return 1" redis-script-load ] with-redis-test
+] unit-test
+
+{ { 0 0 } } [
+    [ { "foo" "bar" } redis-script-exists ] with-redis-test
+] unit-test
+
+{ } [ [ redis-script-flush ] with-redis-test ] unit-test
+
+{ { "foo" } } [
+    [ "return { ARGV[1] }" { } { "foo" } redis-script-eval ] with-redis-test
+] unit-test
index 98e89dca535cbfa656b71ad5ebe17c0b6803ec35..c138dd654ed541e015ac997a69c144b4a56e1e7a 100644 (file)
@@ -90,6 +90,14 @@ IN: redis
 : redis-info ( -- response ) info flush read-response ;
 : redis-monitor ( -- response ) monitor flush read-response ;
 
+! Lua
+: redis-script-load ( script -- script ) script-load flush read-response ;
+: redis-script-exists ( sequence -- sequence ) script-exists flush read-response ;
+: redis-script-flush ( -- ) script-flush flush check-response ;
+: redis-script-kill ( -- ) script-kill flush check-response ;
+: redis-script-eval ( script keys args -- result ) script-eval flush read-response ;
+: redis-script-evalsha ( sha keys args -- result ) script-evalsha flush read-response ;
+
 ! Redis object
 TUPLE: redis host port encoding password ;