Modules: Add REDISMODULE_EVENT_CONFIG (#10311)

Add a new REDISMODULE_EVENT_CONFIG event type for notifying modules when Redis configuration changes.
This commit is contained in:
Shaya Potter 2022-03-07 17:37:57 +02:00 committed by GitHub
parent 45d83fb2d4
commit 23f03e7965
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 66 additions and 3 deletions

View File

@ -709,6 +709,7 @@ void configSetCommand(client *c) {
const char *invalid_arg_name = NULL;
const char *err_arg_name = NULL;
standardConfig **set_configs; /* TODO: make this a dict for better performance */
const char **config_names;
sds *new_values;
sds *old_values = NULL;
apply_fn *apply_fns; /* TODO: make this a set for better performance */
@ -724,6 +725,7 @@ void configSetCommand(client *c) {
config_count = (c->argc - 2) / 2;
set_configs = zcalloc(sizeof(standardConfig*)*config_count);
config_names = zcalloc(sizeof(char*)*config_count);
new_values = zmalloc(sizeof(sds*)*config_count);
old_values = zcalloc(sizeof(sds*)*config_count);
apply_fns = zcalloc(sizeof(apply_fn)*config_count);
@ -779,6 +781,7 @@ void configSetCommand(client *c) {
}
}
set_configs[i] = config;
config_names[i] = config->name;
new_values[i] = c->argv[2+i*2+1]->ptr;
}
@ -824,6 +827,8 @@ void configSetCommand(client *c) {
goto err;
}
}
RedisModuleConfigChangeV1 cc = {.num_changes = config_count, .config_names = config_names};
moduleFireServerEvent(REDISMODULE_EVENT_CONFIG, REDISMODULE_SUBEVENT_CONFIG_CHANGE, &cc);
addReply(c,shared.ok);
goto end;
@ -840,6 +845,7 @@ err:
}
end:
zfree(set_configs);
zfree(config_names);
zfree(new_values);
for (i = 0; i < config_count; i++)
sdsfree(old_values[i]);

View File

@ -9976,6 +9976,7 @@ static uint64_t moduleEventVersions[] = {
-1, /* REDISMODULE_EVENT_FORK_CHILD */
-1, /* REDISMODULE_EVENT_REPL_ASYNC_LOAD */
-1, /* REDISMODULE_EVENT_EVENTLOOP */
-1, /* REDISMODULE_EVENT_CONFIG */
};
/* Register to be notified, via a callback, when the specified server event
@ -10236,6 +10237,20 @@ static uint64_t moduleEventVersions[] = {
* * `REDISMODULE_SUBEVENT_EVENTLOOP_BEFORE_SLEEP`
* * `REDISMODULE_SUBEVENT_EVENTLOOP_AFTER_SLEEP`
*
* * RedisModule_Event_Config
*
* Called when a configuration event happens
* The following sub events are available:
*
* * `REDISMODULE_SUBEVENT_CONFIG_CHANGE`
*
* The data pointer can be casted to a RedisModuleConfigChange
* structure with the following fields:
*
* const char **config_names; // An array of C string pointers containing the
* // name of each modified configuration item
* uint32_t num_changes; // The number of elements in the config_names array
*
* The function returns REDISMODULE_OK if the module was successfully subscribed
* for the specified event. If the API is called from a wrong context or unsupported event
* is given then REDISMODULE_ERR is returned. */
@ -10313,6 +10328,8 @@ int RM_IsSubEventSupported(RedisModuleEvent event, int64_t subevent) {
return subevent < _REDISMODULE_SUBEVENT_FORK_CHILD_NEXT;
case REDISMODULE_EVENT_EVENTLOOP:
return subevent < _REDISMODULE_SUBEVENT_EVENTLOOP_NEXT;
case REDISMODULE_EVENT_CONFIG:
return subevent < _REDISMODULE_SUBEVENT_CONFIG_NEXT;
default:
break;
}
@ -10389,6 +10406,8 @@ void moduleFireServerEvent(uint64_t eid, int subid, void *data) {
moduledata = data;
} else if (eid == REDISMODULE_EVENT_SWAPDB) {
moduledata = data;
} else if (eid == REDISMODULE_EVENT_CONFIG) {
moduledata = data;
}
el->module->in_hook++;

View File

@ -429,7 +429,8 @@ typedef void (*RedisModuleEventLoopOneShotFunc)(void *user_data);
#define REDISMODULE_EVENT_FORK_CHILD 13
#define REDISMODULE_EVENT_REPL_ASYNC_LOAD 14
#define REDISMODULE_EVENT_EVENTLOOP 15
#define _REDISMODULE_EVENT_NEXT 16 /* Next event flag, should be updated if a new event added. */
#define REDISMODULE_EVENT_CONFIG 16
#define _REDISMODULE_EVENT_NEXT 17 /* Next event flag, should be updated if a new event added. */
typedef struct RedisModuleEvent {
uint64_t id; /* REDISMODULE_EVENT_... defines. */
@ -532,7 +533,11 @@ static const RedisModuleEvent
RedisModuleEvent_EventLoop = {
REDISMODULE_EVENT_EVENTLOOP,
1
};
},
RedisModuleEvent_Config = {
REDISMODULE_EVENT_CONFIG,
1
};
/* Those are values that are used for the 'subevent' callback argument. */
#define REDISMODULE_SUBEVENT_PERSISTENCE_RDB_START 0
@ -574,6 +579,9 @@ static const RedisModuleEvent
#define REDISMODULE_SUBEVENT_MODULE_UNLOADED 1
#define _REDISMODULE_SUBEVENT_MODULE_NEXT 2
#define REDISMODULE_SUBEVENT_CONFIG_CHANGE 0
#define _REDISMODULE_SUBEVENT_CONFIG_NEXT 1
#define REDISMODULE_SUBEVENT_LOADING_PROGRESS_RDB 0
#define REDISMODULE_SUBEVENT_LOADING_PROGRESS_AOF 1
#define _REDISMODULE_SUBEVENT_LOADING_PROGRESS_NEXT 2
@ -674,6 +682,17 @@ typedef struct RedisModuleModuleChange {
#define RedisModuleModuleChange RedisModuleModuleChangeV1
#define REDISMODULE_CONFIGCHANGE_VERSION 1
typedef struct RedisModuleConfigChange {
uint64_t version; /* Not used since this structure is never passed
from the module to the core right now. Here
for future compatibility. */
uint32_t num_changes; /* how many redis config options were changed */
const char **config_names; /* the config names that were changed */
} RedisModuleConfigChangeV1;
#define RedisModuleConfigChange RedisModuleConfigChangeV1
#define REDISMODULE_CRON_LOOP_VERSION 1
typedef struct RedisModuleCronLoopInfo {
uint64_t version; /* Not used since this structure is never passed

View File

@ -267,6 +267,18 @@ void swapDbCallback(RedisModuleCtx *ctx, RedisModuleEvent e, uint64_t sub, void
LogNumericEvent(ctx, "swapdb-second", ei->dbnum_second);
}
void configChangeCallback(RedisModuleCtx *ctx, RedisModuleEvent e, uint64_t sub, void *data)
{
REDISMODULE_NOT_USED(e);
if (sub != REDISMODULE_SUBEVENT_CONFIG_CHANGE) {
return;
}
RedisModuleConfigChangeV1 *ei = data;
LogNumericEvent(ctx, "config-change-count", ei->num_changes);
LogStringEvent(ctx, "config-change-first", ei->config_names[0]);
}
/* This function must be present on each Redis module. It is used in order to
* register the commands into the Redis server. */
int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {
@ -317,6 +329,9 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
RedisModule_SubscribeToServerEvent(ctx,
RedisModuleEvent_SwapDB, swapDbCallback);
RedisModule_SubscribeToServerEvent(ctx,
RedisModuleEvent_Config, configChangeCallback);
event_log = RedisModule_CreateDict(ctx);
if (RedisModule_CreateCommand(ctx,"hooks.event_count", cmdEventCount,"",0,0,0) == REDISMODULE_ERR)

View File

@ -150,13 +150,17 @@ tags "modules" {
r swapdb 0 10
assert_equal [r hooks.event_last swapdb-first] 0
assert_equal [r hooks.event_last swapdb-second] 10
}
test {Test configchange hooks} {
r config set rdbcompression no
assert_equal [r hooks.event_last config-change-count] 1
assert_equal [r hooks.event_last config-change-first] rdbcompression
}
# look into the log file of the server that just exited
test {Test shutdown hook} {
assert_equal [string match {*module-event-shutdown*} [exec tail -5 < $replica_stdout]] 1
}
}
}