-
Notifications
You must be signed in to change notification settings - Fork 663
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
Add API UpdateRuntimeArgs to allow the module arguments during runtime and save the new arguments value into the conf file #1041
base: unstable
Are you sure you want to change the base?
Conversation
c52d35c
to
c3341b1
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## unstable #1041 +/- ##
============================================
+ Coverage 70.65% 70.73% +0.07%
============================================
Files 114 116 +2
Lines 63158 63312 +154
============================================
+ Hits 44624 44781 +157
+ Misses 18534 18531 -3
|
3bb1f12
to
9884508
Compare
9884508
to
8a9d80e
Compare
Looks simple, but what's the use case? Why does a module need to update args in runtime? A module can already have config that is updated using CONFIG SET, right? |
eb9712a
to
fbc66dd
Compare
5038d52
to
ed24ce1
Compare
@zuiderkwast I update the top description for this PR, i think this is a good way to access the updated module arguments. Pls take a look when you have time, Thanks a lot |
You added a module API to access the argv. Interesting. But, I am not convinced. :) In a program written in C, the arguments are passed to main as The MODULE UNLOAD + MODULE LOAD doesn't have this problem. |
ed24ce1
to
50aa816
Compare
Thanks for your comment, but some cons for operation MODULE UNLOAD + MODULE LOAD
I would like to create an issue to let community to discuss this problem. Thanks |
50aa816
to
e313f86
Compare
0caa3bd
to
69c5083
Compare
69c5083
to
b4d698d
Compare
@madolson As we discussed, I desgin the API as int VM_UpdateRuntimeArgs(ValkeyModuleCtx *ctx, int argc, ValkeyModuleString **argv), please take a look, Thanks |
b4d698d
to
c35a618
Compare
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.
Looks good to me. Only documentation comment missing.
What about VM_GetRuntimeArgs, is it not needed?
fbc6ca1
to
67e9459
Compare
2d51ed9
to
e260229
Compare
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.
Sorry for many small reviews. I was going to click Approve, but then I read the test case. more carefully and found some strange function and command names. :)
src/module.c
Outdated
if (!ctx->module->onload) { | ||
return VALKEYMODULE_ERR; | ||
} |
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.
Why is this only allowed at startup? I thought the whole point was they were able to update these at any point in time.
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.
Good point. I'm surprised the test case passes.
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 condition "!ctx->module->onload" is checked here is not like what you thought it can be only allowed to update at startup, the goal is to check if ctx->module->onload is NULL to prevent NULL pointer exception. This API can be called at any time during runtime.
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.
I think it means that onload is ongoing. If it doesn't, then there is something wrong.
I tried to follow the function calls that happen when a module is loaded. This is what I could find:
- MODULE LOAD -> moduleCommand -> moduleLoad.
- moduleLoad loads the module file using dlopen.
- moduleLoad finds the ValkeyModule_OnLoad function in the module using dlsym.
- moduleLoad calls the ValkeyModule_OnLoad in the module.
- The module's ValkeyModule_OnLoad function calls ValkeyModule_Init.
- ValkeyModule_Init (implemented in valkeymodule.h) calls ValkeyModule_SetModuleAttribs.
- VM_SetModuleAttribs creates the struct ctx->module and sets ctx->module->onload = 1.
- The ValkeyModule_OnLoad function calls other functions, such as ValkeyModule_CreateCommand
- The ValkeyModule_OnLoad function returns.
- moduleLoad logs serverLog(LL_NOTICE, "Module '%s' loaded from %s", ctx.module->name, path);
- moduleLoad sets ctx.module->onload = 0;
- This ctx is freed, but the module object is added to a dict.
There is no other place that onload is set. That means onload = 1 only when ValkeyModule_OnLoad is running.
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 onload field in ValkeyModule is not a pointer. It is an int.
int onload; /* Flag to identify if the call is being made from Onload (0 or 1) */
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.
Sorry, it looks like on that time, my brain is offline. Yes, you are right, it is int, not pointer. The condition here is useless, I should remove it.
d62c9cd
to
a117ce9
Compare
|
||
int test_module_update_parameter(ValkeyModuleCtx *ctx, | ||
ValkeyModuleString **argv, int argc) { | ||
ValkeyModule_UpdateRuntimeArgs(ctx, argv, argc); |
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.
Check that ValkeyModule_UpdateRuntimeArgs returns VALKEYMODULE_OK here.
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.
Update to: return ValkeyModule_UpdateRuntimeArgs(ctx, argv, argc);
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.
Yes, or
ValkeyModule_UpdateRuntimeArgs(ctx, argv, argc); | |
int res = ValkeyModule_UpdateRuntimeArgs(ctx, argv, argc); | |
assert(res == VALKEYMODULE_OK); |
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 command still needs to send a reply to the client, right?
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.
I just have one statement as return ValkeyModule_ReplyWithSimpleString(ctx, "OK");
357fa75
to
aa2ba36
Compare
set modulename [lmap x [r module list] {dict get $x name}] | ||
assert_not_equal [lsearch $modulename moduleparameter] -1 | ||
assert_equal "{10 20 30}" [lmap x [r module list] {dict get $x args}] | ||
r testmoduleparameter.update.parameter 40 50 60 70 |
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.
It should return OK on success, right?
r testmoduleparameter.update.parameter 40 50 60 70 | |
assert_equal OK [r testmoduleparameter.update.parameter 40 50 60 70] |
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.
Or maybe it returns the string "Module runtime args test", the reply sent by this command in the previous commits.
r testmoduleparameter.update.parameter 40 50 60 70 | |
assert_equal "Module runtime args test" [r testmoduleparameter.update.parameter 40 50 60 70] |
... but OK seems more normal I think 😁
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.
I update this part as assert_equal OK [r testmoduleparameter.update.parameter 40 50 60 70]
158477e
to
05deaf2
Compare
I update some logic in module.c, now it works well. @zuiderkwast |
Signed-off-by: hwware <[email protected]>
Signed-off-by: hwware <[email protected]>
Signed-off-by: hwware <[email protected]>
Signed-off-by: hwware <[email protected]>
Signed-off-by: hwware <[email protected]>
Signed-off-by: hwware <[email protected]>
Signed-off-by: hwware <[email protected]>
Signed-off-by: hwware <[email protected]>
Signed-off-by: hwware <[email protected]>
Signed-off-by: hwware <[email protected]>
Signed-off-by: hwware <[email protected]>
Signed-off-by: hwware <[email protected]>
05deaf2
to
fc31906
Compare
Before Redis OSS 7, if we load a module with some arguments during runtime,
and run the command "config rewrite", the module information will not be saved into the
config file.
Since Redis OSS 7 and Valkey 7.2, if we load a module with some arguments during runtime,
the module information (path, arguments number, and arguments value) can be saved into the config file after config rewrite command is called.
Thus, the module will be loaded automatically when the server startup next time.
Following is one example:
bind 172.25.0.58
port 7000
protected-mode no
enable-module-command yes
Generated by CONFIG REWRITE
latency-tracking-info-percentiles 50 99 99.9
dir "/home/ubuntu/valkey"
save 3600 1 300 100 60 10000
user default on nopass sanitize-payload ~* &* +https://github.com/ALL
loadmodule tests/modules/datatype.so 10 20
However, there is one problem.
If developers write a module, and update the running arguments by someway, the updated arguments can not be saved into the config file even "config rewrite" is called.
The reason comes from the following function
rewriteConfigLoadmoduleOption (src/config.c)
void rewriteConfigLoadmoduleOption(struct rewriteConfigState *state) {
..........
struct ValkeyModule *module = dictGetVal(de);
line = sdsnew("loadmodule ");
line = sdscatsds(line, module->loadmod->path);
for (int i = 0; i < module->loadmod->argc; i++) {
line = sdscatlen(line, " ", 1);
line = sdscatsds(line, module->loadmod->argv[i]->ptr);
}
rewriteConfigRewriteLine(state, "loadmodule", line, 1);
.......
}
The function only save the initial arguments information (module->loadmod) into the configfile.
After core members discuss, ref #1177
We decide add the following API to implement this feature:
Original proposal:
int VM_UpdateRunTimeArgs(ValkeyModuleCtx *ctx, int index, char *value);
Updated proposal:
ValkeyModuleString **values VM_GetRuntimeArgs(ValkeyModuleCtx *ctx);
**int VM_UpdateRuntimeArgs(ValkeyModuleCtx *ctx, int argc, ValkeyModuleString **values);
Why we do not recommend the following way:
MODULE UNLOAD
Update module args in the conf file
MODULE LOAD
I think there are the following disadvantages: