Add new SCRIPT SHOW subcommand to dump script via sha1 (#617)
In some scenarios, the business may not be able to find the previously used Lua script and only have a SHA signature. Or there are multiple identical evalsha's args in monitor/slowlog, and admin is not able to distinguish the script body. Add a new script subcommmand to show the contents of script given the scripts sha1. Returns a NOSCRIPT error if the script is not present in the cache. Usage: `SCRIPT SHOW sha1` Complexity: `O(1)` Closes #604. Doc PR: https://github.com/valkey-io/valkey-doc/pull/143 --------- Signed-off-by: wei.kukey <wei.kukey@gmail.com> Signed-off-by: Madelyn Olson <madelyneolson@gmail.com> Co-authored-by: Madelyn Olson <madelyneolson@gmail.com> Co-authored-by: Binbin <binloveplay1314@qq.com> Co-authored-by: Viktor Söderqvist <viktor.soderqvist@est.tech>
This commit is contained in:
parent
be2c321682
commit
ae2d4217e1
@ -5333,6 +5333,28 @@ struct COMMAND_ARG SCRIPT_LOAD_Args[] = {
|
||||
{MAKE_ARG("script",ARG_TYPE_STRING,-1,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)},
|
||||
};
|
||||
|
||||
/********** SCRIPT SHOW ********************/
|
||||
|
||||
#ifndef SKIP_CMD_HISTORY_TABLE
|
||||
/* SCRIPT SHOW history */
|
||||
#define SCRIPT_SHOW_History NULL
|
||||
#endif
|
||||
|
||||
#ifndef SKIP_CMD_TIPS_TABLE
|
||||
/* SCRIPT SHOW tips */
|
||||
#define SCRIPT_SHOW_Tips NULL
|
||||
#endif
|
||||
|
||||
#ifndef SKIP_CMD_KEY_SPECS_TABLE
|
||||
/* SCRIPT SHOW key specs */
|
||||
#define SCRIPT_SHOW_Keyspecs NULL
|
||||
#endif
|
||||
|
||||
/* SCRIPT SHOW argument table */
|
||||
struct COMMAND_ARG SCRIPT_SHOW_Args[] = {
|
||||
{MAKE_ARG("sha1",ARG_TYPE_STRING,-1,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)},
|
||||
};
|
||||
|
||||
/* SCRIPT command table */
|
||||
struct COMMAND_STRUCT SCRIPT_Subcommands[] = {
|
||||
{MAKE_CMD("debug","Sets the debug mode of server-side Lua scripts.","O(1)","3.2.0",CMD_DOC_NONE,NULL,NULL,"scripting",COMMAND_GROUP_SCRIPTING,SCRIPT_DEBUG_History,0,SCRIPT_DEBUG_Tips,0,scriptCommand,3,CMD_NOSCRIPT,ACL_CATEGORY_SCRIPTING,SCRIPT_DEBUG_Keyspecs,0,NULL,1),.args=SCRIPT_DEBUG_Args},
|
||||
@ -5341,6 +5363,7 @@ struct COMMAND_STRUCT SCRIPT_Subcommands[] = {
|
||||
{MAKE_CMD("help","Returns helpful text about the different subcommands.","O(1)","5.0.0",CMD_DOC_NONE,NULL,NULL,"scripting",COMMAND_GROUP_SCRIPTING,SCRIPT_HELP_History,0,SCRIPT_HELP_Tips,0,scriptCommand,2,CMD_LOADING|CMD_STALE,ACL_CATEGORY_SCRIPTING,SCRIPT_HELP_Keyspecs,0,NULL,0)},
|
||||
{MAKE_CMD("kill","Terminates a server-side Lua script during execution.","O(1)","2.6.0",CMD_DOC_NONE,NULL,NULL,"scripting",COMMAND_GROUP_SCRIPTING,SCRIPT_KILL_History,0,SCRIPT_KILL_Tips,2,scriptCommand,2,CMD_NOSCRIPT|CMD_ALLOW_BUSY,ACL_CATEGORY_SCRIPTING,SCRIPT_KILL_Keyspecs,0,NULL,0)},
|
||||
{MAKE_CMD("load","Loads a server-side Lua script to the script cache.","O(N) with N being the length in bytes of the script body.","2.6.0",CMD_DOC_NONE,NULL,NULL,"scripting",COMMAND_GROUP_SCRIPTING,SCRIPT_LOAD_History,0,SCRIPT_LOAD_Tips,2,scriptCommand,3,CMD_NOSCRIPT|CMD_STALE,ACL_CATEGORY_SCRIPTING,SCRIPT_LOAD_Keyspecs,0,NULL,1),.args=SCRIPT_LOAD_Args},
|
||||
{MAKE_CMD("show","Show server-side Lua script in the script cache.","O(1).","8.0.0",CMD_DOC_NONE,NULL,NULL,"scripting",COMMAND_GROUP_SCRIPTING,SCRIPT_SHOW_History,0,SCRIPT_SHOW_Tips,0,scriptCommand,3,CMD_NOSCRIPT,ACL_CATEGORY_SCRIPTING,SCRIPT_SHOW_Keyspecs,0,NULL,1),.args=SCRIPT_SHOW_Args},
|
||||
{0}
|
||||
};
|
||||
|
||||
|
27
src/commands/script-show.json
Normal file
27
src/commands/script-show.json
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"SHOW": {
|
||||
"summary": "Show server-side Lua script in the script cache.",
|
||||
"complexity": "O(1).",
|
||||
"group": "scripting",
|
||||
"since": "8.0.0",
|
||||
"arity": 3,
|
||||
"container": "SCRIPT",
|
||||
"function": "scriptCommand",
|
||||
"command_flags": [
|
||||
"NOSCRIPT"
|
||||
],
|
||||
"acl_categories": [
|
||||
"SCRIPTING"
|
||||
],
|
||||
"arguments": [
|
||||
{
|
||||
"name": "sha1",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"reply_schema": {
|
||||
"description": "Lua script if sha1 hash exists in script cache.",
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
12
src/eval.c
12
src/eval.c
@ -682,6 +682,8 @@ void scriptCommand(client *c) {
|
||||
" Kill the currently executing Lua script.",
|
||||
"LOAD <script>",
|
||||
" Load a script into the scripts cache without executing it.",
|
||||
"SHOW <sha1>",
|
||||
" Show a script from the scripts cache.",
|
||||
NULL
|
||||
};
|
||||
/* clang-format on */
|
||||
@ -735,6 +737,16 @@ NULL
|
||||
addReplyError(c, "Use SCRIPT DEBUG YES/SYNC/NO");
|
||||
return;
|
||||
}
|
||||
} else if (c->argc == 3 && !strcasecmp(c->argv[1]->ptr, "show")) {
|
||||
dictEntry *de;
|
||||
luaScript *ls;
|
||||
|
||||
if (sdslen(c->argv[2]->ptr) == 40 && (de = dictFind(lctx.lua_scripts, c->argv[2]->ptr))) {
|
||||
ls = dictGetVal(de);
|
||||
addReplyBulk(c, ls->body);
|
||||
} else {
|
||||
addReplyErrorObject(c, shared.noscripterr);
|
||||
}
|
||||
} else {
|
||||
addReplySubcommandSyntaxError(c);
|
||||
}
|
||||
|
@ -1814,7 +1814,7 @@ void createSharedObjects(void) {
|
||||
shared.syntaxerr = createObject(OBJ_STRING, sdsnew("-ERR syntax error\r\n"));
|
||||
shared.sameobjecterr = createObject(OBJ_STRING, sdsnew("-ERR source and destination objects are the same\r\n"));
|
||||
shared.outofrangeerr = createObject(OBJ_STRING, sdsnew("-ERR index out of range\r\n"));
|
||||
shared.noscripterr = createObject(OBJ_STRING, sdsnew("-NOSCRIPT No matching script. Please use EVAL.\r\n"));
|
||||
shared.noscripterr = createObject(OBJ_STRING, sdsnew("-NOSCRIPT No matching script.\r\n"));
|
||||
createSharedObjectsWithCompat();
|
||||
shared.primarydownerr = createObject(
|
||||
OBJ_STRING, sdsnew("-MASTERDOWN Link with MASTER is down and replica-serve-stale-data is set to 'no'.\r\n"));
|
||||
|
@ -638,6 +638,21 @@ start_server {tags {"scripting"}} {
|
||||
[r evalsha b534286061d4b9e4026607613b95c06c06015ae8 0]
|
||||
} {b534286061d4b9e4026607613b95c06c06015ae8 loaded}
|
||||
|
||||
test {SCRIPT SHOW - is able to dump scripts from the scripting cache} {
|
||||
r script load "return 'dump'"
|
||||
r script show 4f5a49d7b18244a3b100d159b78b51474e23e081
|
||||
} {return 'dump'}
|
||||
|
||||
test {SCRIPT SHOW - wrong sha1 length or invalid sha1 char return noscript error} {
|
||||
assert_error {NOSCRIPT*} {r script show b534286061d4b06c06015ae8}
|
||||
assert_error {NOSCRIPT*} {r script show AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA}
|
||||
}
|
||||
|
||||
test {SCRIPT SHOW - script not exist return noscript error} {
|
||||
r script flush
|
||||
assert_error {NOSCRIPT*} {r script show 4f5a49d7b18244a3b100d159b78b51474e23e081}
|
||||
}
|
||||
|
||||
test "SORT is normally not alpha re-ordered for the scripting engine" {
|
||||
r del myset
|
||||
r sadd myset 1 2 3 4 10
|
||||
|
Loading…
x
Reference in New Issue
Block a user