Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Build without Lua scripting via USE_LUA (#1204) #1245

Open
wants to merge 9 commits into
base: unstable
Choose a base branch
from

Conversation

neomantra
Copy link
Contributor

Adds the ability to disable Lua scripting using the build
configuration USE_LUA. This will prevent the building
of the Lua static library and will keep Lua and most Lua
scripting internals out of the build.

This approach strived to minimize the change surface, stubbing out
keys requried functions and otherwise ifdefing out large swathes of code.

The base Lua scripting commands like EVAL remain intact, but reply
with an error message Lua scripting disabled. INFO commands
still include scripting statistics to prevent breaking any DevOps scripts, etc.

There are decisions to make:

  • What do with EVAL commands, etc? Currently, the command still exists but replies with an Error.

  • What to do with testing infrastructure? EVAL is sprinkled throughout. grep -or EVAL tests/unit | wc -l ==> 125. Do we break tests into files with EVAL and ones without?

@neomantra
Copy link
Contributor Author

I see the Test Tags system now and am using that to constrain tests which utilize Lua.

@zuiderkwast
Copy link
Contributor

  • What do with EVAL commands, etc? Currently, the command still exists but replies with an Error.

This sounds right to me.

  • What to do with testing infrastructure? EVAL is sprinkled throughout. grep -or EVAL tests/unit | wc -l ==> 125. Do we break tests into files with EVAL and ones without?

I see the Test Tags system now and am using that to constrain tests which utilize Lua.

Test tag sounds like the best solution. Is it feasible? (If not, maybe we can just run a few selected test suites in the CI for the build without Lua.)

Copy link

codecov bot commented Nov 1, 2024

Codecov Report

Attention: Patch coverage is 75.00000% with 1 line in your changes missing coverage. Please review.

Project coverage is 70.65%. Comparing base (a102852) to head (51a4429).
Report is 6 commits behind head on unstable.

Files with missing lines Patch % Lines
src/object.c 0.00% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##           unstable    #1245      +/-   ##
============================================
- Coverage     70.70%   70.65%   -0.05%     
============================================
  Files           114      114              
  Lines         63157    63159       +2     
============================================
- Hits          44653    44628      -25     
- Misses        18504    18531      +27     
Files with missing lines Coverage Δ
src/defrag.c 84.34% <100.00%> (ø)
src/eval.c 57.15% <100.00%> (+0.09%) ⬆️
src/function_lua.c 99.19% <ø> (ø)
src/functions.c 95.71% <ø> (ø)
src/lazyfree.c 86.11% <ø> (ø)
src/script_lua.c 90.42% <ø> (ø)
src/server.c 87.70% <ø> (-0.04%) ⬇️
src/server.h 100.00% <ø> (ø)
src/object.c 79.15% <0.00%> (ø)

... and 12 files with indirect coverage changes

@neomantra
Copy link
Contributor Author

neomantra commented Nov 1, 2024

Although I perhaps wanted needs:lua, I stuck with the tag scripting. I went through and found all the spots where eval or call were used and where the tests were failing from needing Lua in any way.

It passes tests with both USE_LUA=on and USE_LUA=off on my Mac, but I was having problems with full make check on my Linux boxes... but I had the same problem on unstable : spewing Port <num> was already busy, trying another port.... Maybe related to my IPv4-only network, will look deeper.

See this commit for the tag changes.

@zuiderkwast
Copy link
Contributor

Although I perhaps wanted needs:lua, I stuck with the tag scripting.

I guess needs:lua is better. Scripting is equivalent to Lua now, but we're considering more languages for scripting (such as WASM, #387) so scripting may not always imply Lua in the future.

@neomantra
Copy link
Contributor Author

I hadn't re-run Lua-enabled after fixing some Lua-disabled tests.... this last commit corrects that with the proper empty results.

The expression `dictSize(evalScriptsDict())` is used
a couple times for memory reporting.  `dictSize` is a macro
without NULL checking and used within a `FMTARG` macro in `server.c`.  Overall, this makes it challenging to stub out when
building without the Lua engine.

This change lifts that expression up to its own function `evalScriptsDictSize`.

Signed-off-by: Evan Wies <[email protected]>
Adds the ability to disable Lua scripting using the build
conifguration `USE_LUA`.  This will prevent the building
of the Lua static library and will keep Lua and most Lua
scripting internals out of the build.

This approach strived to minimize the change surface, stubbing out
keys requried functions and otherwise `ifdef`ing out large swathes of code.

The base Lua scripting commands like `EVAL` remain intact, but reply
with an error message `Lua scripting disabled`.  `INFO` commands
still include scripting statistics to prevent breaking any DevOps scripts, etc.

Signed-off-by: Evan Wies <[email protected]>
Adds LUA_TEST_FLAGS to Makefile to propagate filtering of scripting tests.

Expands "scripting" tag to all uses of Lua.

Signed-off-by: Evan Wies <[email protected]>
 * fix ci.yml whitespace, from yamlint
 * fix defrag.c, from -Werror

Signed-off-by: Evan Wies <[email protected]>
@neomantra
Copy link
Contributor Author

Sorry for the repeated build failures -- glad the CI catches it :)

I was missing some targets and hence some Lua coverage. I still cannot do a full test on Linux with unstable. [I hoped #1243 would help, but it didn't. Looked a little at the find_available_port etc and it does feel like a port race.]

 * Make clang linter happy in defrag.c
 * Tag a test as scripting in memefficiency.tcl

Signed-off-by: Evan Wies <[email protected]>
@zuiderkwast zuiderkwast linked an issue Nov 4, 2024 that may be closed by this pull request
@madolson
Copy link
Member

madolson commented Nov 4, 2024

We discussed this in an online meeting. The core team was OK with being able to remove LUA from the server, but we would like to make it more pluggable and modular. Instead of just not installing LUA, we would like to make it so that LUA is not added as an engine (similar to how functions allows you to specify the engine type) and so when you try to run EVAL you get an error like "no default engine loaded". In the future folks can use either Lua 5.4 or LuaJIT.

@neomantra
Copy link
Contributor Author

I made that error message change per your suggestion. Some of that work (modular engine system) is beyond the scope of this PR, but I think it is a sensible approach. At least the USE_LUA injections and scripting test tagging here helps show the surface and some cross-cutting concerns.

If you have specifics to add that are low-hanging, I could explore it.

@zuiderkwast
Copy link
Contributor

There is partial logic for a modular engine system. EVAL currently accepts a shebang that is intended to be able to select the scripting engine in the future.

eval.c-365-        /* Verify lua interpreter was specified */
eval.c:366:        if (strcmp(parts[0], "#!lua")) {
eval.c-367-            if (err) *err = sdscatfmt(sdsempty(), "Unexpected engine in script shebang: %s", parts[0]);
eval.c-368-            sdsfreesplitres(parts, numparts);
eval.c-369-            return C_ERR;
eval.c-370-        }

Here we want the module API to provide a way for modules to provide a scripting engine. I created this issue: #1261.

Copy link
Contributor

@hpatro hpatro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like we allow loading of functions in case the engine doesn't support any engine. Would that cause any confusion? Same thing applies for functions arriving via replication stream.

Comment on lines +1807 to +1825
void evalCommand(client *c) {
addReplyError(c, "No default engine loaded");
}

void evalRoCommand(client *c) {
addReplyError(c, "No default engine loaded");
}

void evalShaCommand(client *c) {
addReplyError(c, "No default engine loaded");
}

void evalShaRoCommand(client *c) {
addReplyError(c, "No default engine loaded");
}

void scriptCommand(client *c) {
addReplyError(c, "No default engine loaded");
}
Copy link
Contributor

@hpatro hpatro Nov 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We would need test to cover these scenarios. So, we might need separate test suite/tag for this particular flow.

Comment on lines 301 to 310
dictDefragFunctions defragfns = {
.defragAlloc = activeDefragAlloc,
.defragKey = (dictDefragAllocFunction *)activeDefragSds,
.defragVal = (val_type == DEFRAG_SDS_DICT_VAL_IS_SDS ? (dictDefragAllocFunction *)activeDefragSds
: val_type == DEFRAG_SDS_DICT_VAL_IS_STROB ? (dictDefragAllocFunction *)activeDefragStringOb
: val_type == DEFRAG_SDS_DICT_VAL_VOID_PTR ? (dictDefragAllocFunction *)activeDefragAlloc
.defragVal = (val_type == DEFRAG_SDS_DICT_VAL_IS_SDS ? (dictDefragAllocFunction *)activeDefragSds
: val_type == DEFRAG_SDS_DICT_VAL_IS_STROB ? (dictDefragAllocFunction *)activeDefragStringOb
: val_type == DEFRAG_SDS_DICT_VAL_VOID_PTR ? (dictDefragAllocFunction *)activeDefragAlloc
#ifdef USE_LUA
: val_type == DEFRAG_SDS_DICT_VAL_LUA_SCRIPT ? (dictDefragAllocFunction *)activeDefragLuaScript
#endif
: NULL)};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be just me. But ifdef within the struct declaration gives a hit to the readability. We can consider refactoring this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe like?

    dictDefragFunctions defragfns = {
        .defragAlloc = activeDefragAlloc,
        .defragKey = (dictDefragAllocFunction *)activeDefragSds,
        .defragVal = (val_type == DEFRAG_SDS_DICT_VAL_IS_SDS     ? (dictDefragAllocFunction *)activeDefragSds
                      : val_type == DEFRAG_SDS_DICT_VAL_IS_STROB ? (dictDefragAllocFunction *)activeDefragStringOb
                      : val_type == DEFRAG_SDS_DICT_VAL_VOID_PTR ? (dictDefragAllocFunction *)activeDefragAlloc
                                                                 : NULL)};
#ifdef USE_LUA
    if (val_type == DEFRAG_SDS_DICT_VAL_LUA_SCRIPT)
        dictDefragFunctions.defragVal = (dictDefragAllocFunction *)activeDefragLuaScript;
#endif

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[NEW] Disable LUA integration during build
4 participants