-
Notifications
You must be signed in to change notification settings - Fork 961
Move Lua scripting engine into a Valkey module #2858
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
base: unstable
Are you sure you want to change the base?
Conversation
This commit restructures the Lua scripting functionality by extracting it from the core Valkey server into a separate Valkey module. This change enables the possibility of a backwards compatible Lua engine upgrade, as well as, the flexibility in building Valkey without the Lua engine. **Important**: from a user's point of view, there's no difference in using the `EVAL` of `FUNCTION/FCALL` scripts. This PR is fully backward compatible with respect to the public API. The main code change is the move and adaptation of the Lua engine source files from `src/lua` to `src/modules/lua`. The original Lua engine code is adapted to use the module API to compile and execute scripts. The main difference between the original code and the new, is the serialization and deserialization of Valkey RESP values into, and from, Lua values. While in the original implementation the parsing of RESP values was done directly from the client buffer, in the new implementation the parsing is done from the `ValkeyModuleCallReply` object and respective API. The Makefile and CMake build systems were also updated to build and integrate the new Lua engine module, within the Valkey server build workflow. When the Valkey server is built, the Lua engine module is also built, and, the Lua module is loaded automatically by the server upon startup. When running `make install` the Lua engine module is installed in the default system library directory. There's a new build option, called `WITHOUT_LUA`, that if set allows to build Valkey server without building the Lua engine. This modular architecture enables future development of additional Lua engine modules with newer Lua versions that can be loaded alongside the current engine, facilitating gradual migration paths for users. Signed-off-by: Ricardo Dias <[email protected]>
|
Wow! Some initial comments:
|
Sure, that makes more sense. I'll update the PR.
I was thinking that if the lua module is built then it would always be loaded by default. But we can add a new config to disable auto-loading even if the lua module is built.
Yes |
Yeah, we can discuss it with the core team. I believe in many contexts, such as in pre-built containers, the module is already built. Many users don't build their own binaries. |
|
I think it makes sense to have that config option to disable auto-load. |
Signed-off-by: Ricardo Dias <[email protected]>
Signed-off-by: Ricardo Dias <[email protected]>
@zuiderkwast I vote for implementing such option in a follow up PR. This PR is already huge to review. |
Signed-off-by: Ricardo Dias <[email protected]>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## unstable #2858 +/- ##
============================================
+ Coverage 72.47% 73.87% +1.40%
============================================
Files 129 125 -4
Lines 70537 68775 -1762
============================================
- Hits 51121 50810 -311
+ Misses 19416 17965 -1451
🚀 New features to boost your workflow:
|
Signed-off-by: Ricardo Dias <[email protected]>
zuiderkwast
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just some initial comments. I'll do another pass later. The change is not as huge as the +/- numbers indicate. Many lines are moved to other files.
The build options should be mentioned in the README.md.
Signed-off-by: Ricardo Dias <[email protected]>
Signed-off-by: Ricardo Dias <[email protected]>
zuiderkwast
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks pretty solid in general.
My main concerns are about the build-time changes. Is there a risk that it will break compilation or installation for any user?
If Valkey is build with BUILD_LUA=no, then it doesn't automatically load a lua module even if such module is installed in the system later. Maybe it's not bad, but I just want to mention it.
@valkey-io/valkey-committers Does anyone else want to take a look, especially on the compile-time changes (Makefiles etc.)?
I tried my best to not break it, but a another pair of eyes is needed to improve confidence on the changes.
Right. But if later someone installs the module separately, it can add a |
Signed-off-by: Ricardo Dias <[email protected]>
Signed-off-by: Ricardo Dias <[email protected]>
Signed-off-by: Ricardo Dias <[email protected]>
Signed-off-by: Ricardo Dias <[email protected]>
Signed-off-by: Ricardo Dias <[email protected]>
Signed-off-by: Ricardo Dias <[email protected]>
Signed-off-by: Ricardo Dias <[email protected]>
Signed-off-by: Ricardo Dias <[email protected]>
Signed-off-by: Ricardo Dias <[email protected]>
Signed-off-by: Ricardo Dias <[email protected]>
|
Do you know why the external tests are failing? I can see this in the logs: When I check |
I'm investigating. This is not the first time that fails in the same assertion, it should be something caused by this PR. |
zuiderkwast
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few random comments and questions. See below.
| LUA_MODULE_INSTALL=install-lua-module | ||
|
|
||
| current_dir = $(shell pwd) | ||
| FINAL_CFLAGS+=-DLUA_ENGINE_ENABLED -DLUA_ENGINE_LIB=libvalkeylua.so |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does the "ENGINE" part of these names add? I imagine just LUA_ENABLED and LUA_LIB are more concise and clear.
| FINAL_CFLAGS+=-DLUA_ENGINE_ENABLED -DLUA_ENGINE_LIB=libvalkeylua.so | |
| FINAL_CFLAGS+=-DLUA_ENABLED -DLUA_LIB=libvalkeylua.so |
|
|
||
| LIBS= $(DEPS_DIR)/lua/src/liblua.a $(DEPS_DIR)/fpconv/libfpconv.a | ||
| SRCS= $(wildcard *.c) | ||
| OBJS= $(SRCS:.c=.o) sha1.o rand.o |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The lua module depends on sha1 and rand from Valkey and fpconv from Valkey deps? (You removed dependency to sds, adlist and stuff like ll2string though.) Is this a problem? An alternative is to provide SHA1, random and float-parsing in the module API.
Let's create a modules/lua/README.md file that explains how this module is independent (or not) to the valkey's source code and other relevant information about it. I can imagine future contributors might add dependency on valkey internals again unless there is some text describing the ideas here.
How do we handle these dependencies in an external Lua 5.4 module? Do we copy these dependencies to that module? (If the module and the core use different versions of e.g. fpconv, would it work?)
| * Based on the following article (that apparently does not provide a | ||
| * novel approach but only publicizes an already used technique): | ||
| * | ||
| * https://www.facebook.com/notes/facebook-engineering/three-optimization-tips-for-c/10151361643253920 */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This link doesn't seem to work anymore (or it requires login). We can skip it or use wayback machine. I found a link that works:
| * https://www.facebook.com/notes/facebook-engineering/three-optimization-tips-for-c/10151361643253920 */ | |
| * https://web.archive.org/web/20150427221229/https://www.facebook.com/notes/facebook-engineering/three-optimization-tips-for-c/10151361643253920 */ |
We could also just delete the link.
| old_s = s; | ||
| s = ValkeyModule_CreateStringPrintf(NULL, "%s %g", prefix, (double)lua_tonumber(lua, idx)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the TNUMBER case, isn't there an extra space added in the format "%s %g"? Before this change, it used sdscatprintf with the format "%g" which doesn't insert a space before the number.
I see old_s is freed in the end of the function. I think the code is easier to follow if make this variable local to this case and free it locally. Same with the prefix variable, either move it to the local scope or we don't need it at all?
| old_s = s; | |
| s = ValkeyModule_CreateStringPrintf(NULL, "%s %g", prefix, (double)lua_tonumber(lua, idx)); | |
| ValkeyModuleString old_s = s; | |
| s = ValkeyModule_CreateStringPrintf(NULL, "%s%g", | |
| ValkeyModule_StringPtrLen(s, NULL), | |
| (double)lua_tonumber(lua, idx)); | |
| ValkeyModule_FreeString(NULL, old_s); |
|
|
||
| static void _serverPanic(const char *file, int line, const char *msg, ...) { | ||
| fprintf(stderr, "------------------------------------------------"); | ||
| fprintf(stderr, "!!! Software Failure."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| fprintf(stderr, "!!! Software Failure."); | |
| fprintf(stderr, "!!! Software Failure. Press left mouse button to continue."); |
It's from Amiga. Left button doesn't make sense anymore but it's part of the original message. Do you think it's silly to keep it?
- https://en.wikipedia.org/wiki/Guru_Meditation
- https://www.generationamiga.com/2023/01/03/one-of-the-weirdest-names-for-an-error-message-but-what-is-a-guru-meditation/
Alternative:
Should we add a ValkeyModule_Panic wrapper, similar to ValkeyModule_Assert?
This PR restructures the Lua scripting functionality by extracting
it from the core Valkey server into a separate Valkey module. This change
enables the possibility of a backwards compatible Lua engine upgrade, as well
as, the flexibility in building Valkey without the Lua engine.
Important: from a user's point of view, there's no difference in using
the
EVALofFUNCTION/FCALLscripts. This PR is fully backward compatiblewith respect to the public API.
The main code change is the move and adaptation of the Lua engine source
files from
src/luatosrc/modules/lua. The original Lua engine code isadapted to use the module API to compile and execute scripts.
The main difference between the original code and the new, is the
serialization and deserialization of Valkey RESP values into, and from,
Lua values. While in the original implementation the parsing of RESP values
was done directly from the client buffer, in the new implementation the
parsing is done from the
ValkeyModuleCallReplyobject and respective API.The Makefile and CMake build systems were also updated to build and
integrate the new Lua engine module, within the Valkey server build
workflow.
When the Valkey server is built, the Lua engine module is also built,
and, the Lua module is loaded automatically by the server upon startup.
When running
make installthe Lua engine module is installed in thedefault system library directory.
There's a new build option, called
BUILD_LUA, that if set tonoallows tobuild Valkey server without building the Lua engine.
This modular architecture enables future development of additional Lua
engine modules with newer Lua versions that can be loaded alongside the
current engine, facilitating gradual migration paths for users.
Fixes: #1627