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

Adds support for scripting engines as Valkey modules #1277

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

Conversation

rjd15372
Copy link
Contributor

@rjd15372 rjd15372 commented Nov 8, 2024

This PR extends the module API to support the addition of different scripting engines to execute user defined functions.

The scripting engine can be implemented as a Valkey module, and can be dynamically loaded with the loadmodule config directive, or with the MODULE LOAD command.

This PR also adds an example of a dummy scripting engine module, to show how to use the new module API. The dummy module is implemented in tests/modules/helloscripting.c.

The current module API support, only allows to load scripting engines to run functions using FCALL command.

In a follow up PR, we will move the Lua scripting engine implmentation into its own module.

@rjd15372
Copy link
Contributor Author

rjd15372 commented Nov 8, 2024

I'm opening this PR in draft mode because I still need to fix test failures, and add new tests as well.

Copy link

codecov bot commented Nov 8, 2024

Codecov Report

Attention: Patch coverage is 68.42105% with 48 lines in your changes missing coverage. Please review.

Project coverage is 70.70%. Comparing base (86f33ea) to head (4b3e858).

Files with missing lines Patch % Lines
src/functions.c 65.71% 24 Missing ⚠️
src/module.c 61.11% 21 Missing ⚠️
src/rdb.c 57.14% 3 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##           unstable    #1277      +/-   ##
============================================
+ Coverage     70.55%   70.70%   +0.14%     
============================================
  Files           115      115              
  Lines         63158    63231      +73     
============================================
+ Hits          44561    44707     +146     
+ Misses        18597    18524      -73     
Files with missing lines Coverage Δ
src/aof.c 80.13% <100.00%> (ø)
src/function_lua.c 99.19% <100.00%> (ø)
src/server.h 100.00% <ø> (ø)
src/strl.c 97.43% <100.00%> (+0.88%) ⬆️
src/rdb.c 76.72% <57.14%> (+0.05%) ⬆️
src/module.c 10.17% <61.11%> (+0.52%) ⬆️
src/functions.c 92.00% <65.71%> (-3.69%) ⬇️

... and 9 files with indirect coverage changes

@rjd15372 rjd15372 marked this pull request as ready for review November 8, 2024 14:52
@rjd15372 rjd15372 force-pushed the engine-api-1261 branch 2 times, most recently from 4a2e223 to 1a808b2 Compare November 8, 2024 16:13
@rjd15372
Copy link
Contributor Author

rjd15372 commented Nov 8, 2024

I just realized I still need to implement the MODULE UNLOAD support. The existing code was not prepared to allow the deletion of a scripting engine.

@madolson madolson added the major-decision-pending Major decision pending by TSC team label Nov 11, 2024
@madolson
Copy link
Member

Core team said we are directionally aligned with, we still want someone to take a deeper look to make sure the details makes sense.

@rjd15372 rjd15372 force-pushed the engine-api-1261 branch 5 times, most recently from fe56090 to 9d4b296 Compare November 11, 2024 17:35
@rjd15372
Copy link
Contributor Author

The PR is ready for review.

Copy link
Contributor

@zuiderkwast zuiderkwast left a comment

Choose a reason for hiding this comment

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

This looks like great progress. Is it ready for a proper review or are you going to change much more?

Shall we do EVAL as a follow-up PR?

Each engine has only one context which is used for all calls, right? Would it be possible for an engine to use a context (or sub-context, etc.) for each client? This idea came up in the LuaJIT discussion by @secwall in #1229. A separate Lua context per client would isolate each client from each other, which compensates for the fact that Lua isn't completely sandboxed by design. Maybe the engine can organize this by itself, if the engine just has access to the current client at the time of a FCALL or EVAL?

tests/modules/helloscripting.c Outdated Show resolved Hide resolved
src/functions.c Outdated Show resolved Hide resolved
tests/unit/moduleapi/scriptingengine.tcl Show resolved Hide resolved
src/valkeymodule.h Outdated Show resolved Hide resolved
@rjd15372
Copy link
Contributor Author

This looks like great progress. Is it ready for a proper review or are you going to change much more?

It's ready. I don't think I'll add more changes apart from the changes asked by the reviewers.

Shall we do EVAL as a follow-up PR?

Yes, that's the plan.

Each engine has only one context which is used for all calls, right? Would it be possible for an engine to use a context (or sub-context, etc.) for each client? This idea came up in the LuaJIT discussion by @secwall in #1229. A separate Lua context per client would isolate each client from each other, which compensates for the fact that Lua isn't completely sandboxed by design. Maybe the engine can organize this by itself, if the engine just has access to the current client at the time of a FCALL or EVAL?

I'll take a look if it's possible, and will open a follow-up PR with the changes.

This commit extends the module API to support the addition of different
scripting engines to run user defined functions.

The scripting engine can be implemented as a Valkey module, and can be
dynamically loaded with the `loadmodule` config directive, or with
the `MODULE LOAD` command.

The current module API support, only allows to load scripting engines to
run functions using `FCALL` command.

In a follow up PR, we will move the Lua scripting engine implmentation
into its own module.

Signed-off-by: Ricardo Dias <[email protected]>
This commit adds a module with a very simple stack based scripting
language implementation to test the new module API that allows to
implement new scripting engines as modules.

Signed-off-by: Ricardo Dias <[email protected]>
@zuiderkwast
Copy link
Contributor

Can you avoid force-pushing? It's easier to review what's changed since last time if you just push small commits. You can even merge unstable to it, rather than rebase. We squash-merge PRs anyway in the end and we use the PR title and description as the commit message.

@rjd15372
Copy link
Contributor Author

Can you avoid force-pushing? It's easier to review what's changed since last time if you just push small commits. You can even merge unstable to it, rather than rebase. We squash-merge PRs anyway in the end and we use the PR title and description as the commit message.

Ah sorry. I wasn't aware that we were squashing the commits upon merge. I'll stop force-pushing.

@rjd15372
Copy link
Contributor Author

Today I added more test cases to test the error code paths.

if (luaL_loadbuffer(lua, blob, sdslen(blob), "@user_function")) {
*err = sdscatprintf(sdsempty(), "Error compiling function: %s", lua_tostring(lua, -1));
if (luaL_loadbuffer(lua, blob, strlen(blob), "@user_function")) {
*err = valkey_asprintf("Error compiling function: %s", lua_tostring(lua, -1));
Copy link
Member

Choose a reason for hiding this comment

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

What is the benefit of valkey_asprintf over sdscatprintf? err has been traditionally an sds string. It is not interchangeable with the normal pointer. This change would add cognitive load so I would like to better understand the rationale behind this change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
major-decision-pending Major decision pending by TSC team
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants