valkey-io / valkey

A flexible distributed key-value datastore that supports both caching and beyond caching workloads.
https://valkey.io
Other
16.96k stars 632 forks source link

[NEW]Update the module args during runtime and save the new args value into the conf file #1177

Open hwware opened 1 week ago

hwware commented 1 week ago

The problem/use-case that the feature addresses Before Redis OSS 7, if we load a module with some args during runtime, and run the command "config rewrite", the module information will not be saved into the conf file.

Since Redis OSS 7 and Valkey 7.2, if we load a module with some args during runtime, the module information (path, args number, and args value) can be saved into the conf 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 ~ & +@all loadmodule tests/modules/datatype.so 10 20

However there is one problem. If developers write a module, and update the running args by someway, the updated args can not be saved into the conf 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 args information (module->loadmod) into the conf file.

Description of the feature

There are 2 ways to solve the problem:

Solution 1: It needs to take 2 steps.

step 1: client calls command: MODULE SET-ARGUMENT [args...] to update the args (module->loadmod) during runtime step 2: client gets the updated args (module->loadmod) in the module through the new API ValkeyModule_GetRunTimeArgs(ctx); Reference: https://github.com/valkey-io/valkey/pull/1041

Solution 2: it only takes 1 step

Call int VM_UpdateRunTimeArgs(ValkeyModuleCtx ctx, int index, char value) API in the module and update the specific args according to the index (module->loadmod). Reference: https://github.com/hwware/valkey/pull/8

Thus, I think the best way is to add a Module API to implement the above 2 features.

Alternatives you've considered

Administrators or developer could update the module args by the following way:

MODULE UNLOAD Update module args in the conf file MODULE LOAD

But I think there are following disadvantages:

  1. some modules can not be unloaded. Such as the example module datatype.so, which is tests/modules/datatype.so
  2. it is not atomic operation for MODULE UNLOAD + MODULE LOAD
  3. sometimes, if we just run the module unload, the client business could be interrupted

Additional information

Any additional information that is relevant to the feature request.

hwware commented 1 week ago

https://github.com/valkey-io/valkey/issues/1079

wuranxx commented 1 week ago

In Redis7, a new module configuration mode is added. This mode seems to be more readable and elegant than adding parameters after loadmodule. In addition, this mode can control module configuration like the native Redis configuration.https://github.com/redis/redis/pull/10285

Can this feature replace the way that add parameters after loadmodules? Do we recommend adding module parameters in a new way in valkey?

hwware commented 1 week ago

one of solutions is to add a module API to allow module developer to update the args as below:

ValkeyModule_UpdateRunTimeArgs(ValkeyModuleCtx ctx, int index, char value) index is the arg index, and value is new args value

The example is here https://github.com/hwware/valkey/pull/8