review from AI changes

This commit is contained in:
Joan Fontanals Martinez 2026-05-26 10:30:23 +02:00
parent bac0a1cc16
commit e2bbd5e4ed
2 changed files with 147 additions and 139 deletions

View file

@ -148,7 +148,7 @@ struct RedisModuleCtx {
gets called for clients blocked
on keys. */
/* Used if there is the REDISMODULE_CTX_KEYS_POS_REQUEST or
/* Used if there is the REDISMODULE_CTX_KEYS_POS_REQUEST or
* REDISMODULE_CTX_CHANNEL_POS_REQUEST flag set. */
getKeysResult *keys_result;
@ -476,8 +476,8 @@ struct ModuleConfig {
sds name; /* Fullname of the config (as it appears in the config file) */
sds alias; /* Optional alias for the configuration. NULL if none exists */
int unprefixedFlag; /* Indicates if the REDISMODULE_CONFIG_UNPREFIXED flag was set.
* If the configuration name was prefixed,during get_fn/set_fn
int unprefixedFlag; /* Indicates if the REDISMODULE_CONFIG_UNPREFIXED flag was set.
* If the configuration name was prefixed,during get_fn/set_fn
* callbacks, it should be reported without the prefix */
void *privdata; /* Optional data passed into the module config callbacks */
@ -1116,14 +1116,14 @@ int RM_IsChannelsPositionRequest(RedisModuleCtx *ctx) {
* registration, the command implementation checks for this special call
* using the RedisModule_IsChannelsPositionRequest() API and uses this
* function in order to report the channels.
*
*
* The supported flags are:
* * REDISMODULE_CMD_CHANNEL_SUBSCRIBE: This command will subscribe to the channel.
* * REDISMODULE_CMD_CHANNEL_UNSUBSCRIBE: This command will unsubscribe from this channel.
* * REDISMODULE_CMD_CHANNEL_PUBLISH: This command will publish to this channel.
* * REDISMODULE_CMD_CHANNEL_PATTERN: Instead of acting on a specific channel, will act on any
* * REDISMODULE_CMD_CHANNEL_PATTERN: Instead of acting on a specific channel, will act on any
* channel specified by the pattern. This is the same access
* used by the PSUBSCRIBE and PUNSUBSCRIBE commands available
* used by the PSUBSCRIBE and PUNSUBSCRIBE commands available
* in Redis. Not intended to be used with PUBLISH permissions.
*
* The following is an example of how it could be used:
@ -1531,13 +1531,13 @@ int populateArgsStructure(struct redisCommandArg *args) {
/* RedisModule_AddACLCategory can be used to add new ACL command categories. Category names
* can only contain alphanumeric characters, underscores, or dashes. Categories can only be added
* during the RedisModule_OnLoad function. Once a category has been added, it can not be removed.
* during the RedisModule_OnLoad function. Once a category has been added, it can not be removed.
* Any module can register a command to any added categories using RedisModule_SetCommandACLCategories.
*
*
* Returns:
* - REDISMODULE_OK on successfully adding the new ACL category.
* - REDISMODULE_OK on successfully adding the new ACL category.
* - REDISMODULE_ERR on failure.
*
*
* On error the errno is set to:
* - EINVAL if the name contains invalid characters.
* - EBUSY if the category name already exists.
@ -1583,9 +1583,9 @@ int matchAclCategoryFlag(char *flag, int64_t *acl_categories_flags) {
}
/* Helper for RM_SetCommandACLCategories(). Turns a string representing acl category
* flags into the acl category flags used by Redis ACL which allows users to access
* flags into the acl category flags used by Redis ACL which allows users to access
* the module commands by acl categories.
*
*
* It returns the set of acl flags, or -1 if unknown flags are found. */
int64_t categoryFlagsFromString(char *aclflags) {
int count, j;
@ -1606,12 +1606,12 @@ int64_t categoryFlagsFromString(char *aclflags) {
/* RedisModule_SetCommandACLCategories can be used to set ACL categories to module
* commands and subcommands. The set of ACL categories should be passed as
* a space separated C string 'aclflags'.
*
* Example, the acl flags 'write slow' marks the command as part of the write and
*
* Example, the acl flags 'write slow' marks the command as part of the write and
* slow ACL categories.
*
*
* On success REDISMODULE_OK is returned. On error REDISMODULE_ERR is returned.
*
*
* This function can only be called during the RedisModule_OnLoad function. If called
* outside of this function, an error is returned.
*/
@ -1843,7 +1843,7 @@ int RM_SetCommandACLCategories(RedisModuleCommand *command, const char *aclflags
*
* Other flags:
*
* * `REDISMODULE_CMD_KEY_NOT_KEY`: The key is not actually a key, but
* * `REDISMODULE_CMD_KEY_NOT_KEY`: The key is not actually a key, but
* should be routed in cluster mode as if it was a key.
*
* * `REDISMODULE_CMD_KEY_INCOMPLETE`: The keyspec might not point out all
@ -2424,7 +2424,7 @@ ustime_t RM_CachedMicroseconds(void) {
* RM_BlockedClientMeasureTimeStart() and RM_BlockedClientMeasureTimeEnd()
* to accumulate independent time intervals to the background duration.
* This method always return REDISMODULE_OK.
*
*
* This function is not thread safe, If used in module thread and blocked callback (possibly main thread)
* simultaneously, it's recommended to protect them with lock owned by caller instead of GIL. */
int RM_BlockedClientMeasureTimeStart(RedisModuleBlockedClient *bc) {
@ -2437,7 +2437,7 @@ int RM_BlockedClientMeasureTimeStart(RedisModuleBlockedClient *bc) {
* On success REDISMODULE_OK is returned.
* This method only returns REDISMODULE_ERR if no start time was
* previously defined ( meaning RM_BlockedClientMeasureTimeStart was not called ).
*
*
* This function is not thread safe, If used in module thread and blocked callback (possibly main thread)
* simultaneously, it's recommended to protect them with lock owned by caller instead of GIL. */
int RM_BlockedClientMeasureTimeEnd(RedisModuleBlockedClient *bc) {
@ -2551,7 +2551,7 @@ void RM_Yield(RedisModuleCtx *ctx, int flags, const char *busy_reply) {
*
* REDISMODULE_OPTION_NO_IMPLICIT_SIGNAL_MODIFIED:
* See RM_SignalModifiedKey().
*
*
* REDISMODULE_OPTIONS_HANDLE_REPL_ASYNC_LOAD:
* Setting this flag indicates module awareness of diskless async replication (repl-diskless-load=swapdb)
* and that redis could be serving reads during replication instead of blocking with LOADING status.
@ -3288,9 +3288,9 @@ int RM_ReplyWithArray(RedisModuleCtx *ctx, long len) {
*
* If the connected client is using RESP2, the reply will be converted to a flat
* array.
*
*
* Use RM_ReplySetMapLength() to set deferred length.
*
*
* The function always returns REDISMODULE_OK. */
int RM_ReplyWithMap(RedisModuleCtx *ctx, long len) {
return moduleReplyWithCollection(ctx, len, COLLECTION_REPLY_MAP);
@ -3307,7 +3307,7 @@ int RM_ReplyWithMap(RedisModuleCtx *ctx, long len) {
* array type.
*
* Use RM_ReplySetSetLength() to set deferred length.
*
*
* The function always returns REDISMODULE_OK. */
int RM_ReplyWithSet(RedisModuleCtx *ctx, long len) {
return moduleReplyWithCollection(ctx, len, COLLECTION_REPLY_SET);
@ -3322,12 +3322,12 @@ int RM_ReplyWithSet(RedisModuleCtx *ctx, long len) {
* See Reply APIs section for more details.
*
* Use RM_ReplySetAttributeLength() to set deferred length.
*
*
* Not supported by RESP2 and will return REDISMODULE_ERR, otherwise
* the function always returns REDISMODULE_OK. */
int RM_ReplyWithAttribute(RedisModuleCtx *ctx, long len) {
if (ctx->client->resp == 2) return REDISMODULE_ERR;
return moduleReplyWithCollection(ctx, len, COLLECTION_REPLY_ATTRIBUTE);
}
@ -3574,7 +3574,7 @@ int RM_ReplyWithCallReply(RedisModuleCtx *ctx, RedisModuleCallReply *reply) {
* a string into a C buffer, and then calling the function
* RedisModule_ReplyWithStringBuffer() with the buffer and length.
*
* In RESP3 the string is tagged as a double, while in RESP2 it's just a plain string
* In RESP3 the string is tagged as a double, while in RESP2 it's just a plain string
* that the user will have to parse.
*
* The function always returns REDISMODULE_OK. */
@ -3588,7 +3588,7 @@ int RM_ReplyWithDouble(RedisModuleCtx *ctx, double d) {
/* Reply with a RESP3 BigNumber type.
* Visit https://github.com/antirez/RESP3/blob/master/spec.md for more info about RESP3.
*
* In RESP3, this is a string of length `len` that is tagged as a BigNumber,
* In RESP3, this is a string of length `len` that is tagged as a BigNumber,
* however, it's up to the caller to ensure that it's a valid BigNumber.
* In RESP2, this is just a plain bulk string response.
*
@ -3744,7 +3744,7 @@ RedisModuleString *RM_GetClientUserNameById(RedisModuleCtx *ctx, uint64_t id) {
errno = ENOENT;
return NULL;
}
if (client->user == NULL) {
errno = ENOTSUP;
return NULL;
@ -4341,7 +4341,7 @@ int RM_SetExpire(RedisModuleKey *key, mstime_t expire) {
return REDISMODULE_ERR;
if (expire != REDISMODULE_NO_EXPIRE) {
expire += commandTimeSnapshot();
/* setExpire() might realloc kvobj */
/* setExpire() might realloc kvobj */
key->kv = setExpire(key->ctx->client,key->db,key->key,expire);
} else {
removeExpire(key->db,key->key);
@ -4362,7 +4362,7 @@ mstime_t RM_GetAbsExpire(RedisModuleKey *key) {
/* Set a new expire for the key. If the special expire
* REDISMODULE_NO_EXPIRE is set, the expire is cancelled if there was
* one (the same as the PERSIST command).
*
*
* Note that the expire must be provided as a positive integer representing
* the absolute Unix timestamp the key should have.
*
@ -4426,8 +4426,8 @@ int RM_SetAbsExpire(RedisModuleKey *key, mstime_t expire) {
* .free_effort = myMeta_FreeEffortCallback
* }
*
* Redis does NOT take ownership of the config structure itself. The `confPtr`
* parameter only needs to remain valid during the RM_CreateKeyMetaClass() call
* Redis does NOT take ownership of the config structure itself. The `confPtr`
* parameter only needs to remain valid during the RM_CreateKeyMetaClass() call
* and can be freed immediately after.
*
* * **version**: Module must set it to REDISMODULE_KEY_META_VERSION. This field is
@ -4553,7 +4553,7 @@ RedisModuleKeyMetaClassId RM_CreateKeyMetaClass(RedisModuleCtx *ctx,
void *confPtr)
{
RedisModuleKeyMetaClassId id;
/* Allow registration during OnLoad, server startup, or when debug flag is set */
int ctx_flags = RM_GetContextFlags(ctx);
if (!ctx->module->onload &&
@ -4563,7 +4563,7 @@ RedisModuleKeyMetaClassId RM_CreateKeyMetaClass(RedisModuleCtx *ctx,
if (!confPtr)
return -2;
/* This structure supposed to evolve over time and defines the superset of all
* module type methods supported across different Redis module API versions */
struct KeyMetaConfAllVersions {
@ -4579,11 +4579,11 @@ RedisModuleKeyMetaClassId RM_CreateKeyMetaClass(RedisModuleCtx *ctx,
KeyMetaLoadFunc rdb_load;
KeyMetaSaveFunc rdb_save;
KeyMetaAOFRewriteFunc aof_rewrite;
KeyMetaDefragFunc defrag;
KeyMetaDefragFunc defrag;
KeyMetaMemUsageFunc mem_usage;
KeyMetaFreeEffortFunc free_effort;
} *legacy = (struct KeyMetaConfAllVersions *)confPtr;
if (legacy->version == 0 || legacy->version > REDISMODULE_KEY_META_VERSION)
return -3;
@ -4607,7 +4607,7 @@ RedisModuleKeyMetaClassId RM_CreateKeyMetaClass(RedisModuleCtx *ctx,
id = keyMetaClassCreate(ctx->module, metaname, metaver, &conf);
if (id == 0) return -4;
return id;
}
@ -4637,10 +4637,10 @@ int RM_SetKeyMeta(RedisModuleKeyMetaClassId id, RedisModuleKey *key, uint64_t me
int RM_GetKeyMeta(RedisModuleKeyMetaClassId id, RedisModuleKey *key, uint64_t *metadata) {
if ((!key) || (key->kv == NULL) || (!metadata))
return REDISMODULE_ERR;
if (keyMetaGetMetadata(id, key->kv, metadata) == 0)
return REDISMODULE_ERR;
return REDISMODULE_OK;
}
@ -5185,7 +5185,7 @@ int moduleZsetAddFlagsFromCoreFlags(int flags) {
*
* REDISMODULE_ZADD_XX: Element must already exist. Do nothing otherwise.
* REDISMODULE_ZADD_NX: Element must not exist. Do nothing otherwise.
* REDISMODULE_ZADD_GT: If element exists, new score must be greater than the current score.
* REDISMODULE_ZADD_GT: If element exists, new score must be greater than the current score.
* Do nothing otherwise. Can optionally be combined with XX.
* REDISMODULE_ZADD_LT: If element exists, new score must be less than the current score.
* Do nothing otherwise. Can optionally be combined with XX.
@ -5831,12 +5831,12 @@ int RM_HashSet(RedisModuleKey *key, int flags, ...) {
* expecting a RedisModuleString pointer to pointer, the function just
* reports if the field exists or not and expects an integer pointer
* as the second element of each pair.
*
*
* REDISMODULE_HASH_EXPIRE_TIME: retrieves the expiration time of a field in the hash.
* The function expects a `mstime_t` pointer as the second element of each pair.
* If the field does not exist or has no expiration, the value is set to
* If the field does not exist or has no expiration, the value is set to
* `REDISMODULE_NO_EXPIRE`. This flag must not be used with `REDISMODULE_HASH_EXISTS`.
*
*
* Example of REDISMODULE_HASH_CFIELDS:
*
* RedisModuleString *username, *hashedpass;
@ -5849,9 +5849,9 @@ int RM_HashSet(RedisModuleKey *key, int flags, ...) {
*
* Example of REDISMODULE_HASH_EXPIRE_TIME:
*
* mstime_t hpExpireTime;
* mstime_t hpExpireTime;
* RedisModule_HashGet(mykey,REDISMODULE_HASH_EXPIRE_TIME,"hp",&hpExpireTime,NULL);
*
*
* The function returns REDISMODULE_OK on success and REDISMODULE_ERR if
* the key is not a hash value.
*
@ -5869,8 +5869,8 @@ int RM_HashGet(RedisModuleKey *key, int flags, ...) {
hfeFlags = HFE_LAZY_ACCESS_EXPIRED; /* allow read also expired fields */
/* Verify flag HASH_EXISTS is not set together with HASH_EXPIRE_TIME */
if ((flags & REDISMODULE_HASH_EXISTS) && (flags & REDISMODULE_HASH_EXPIRE_TIME))
return REDISMODULE_ERR;
if ((flags & REDISMODULE_HASH_EXISTS) && (flags & REDISMODULE_HASH_EXPIRE_TIME))
return REDISMODULE_ERR;
va_start(ap, flags);
while(1) {
@ -5895,7 +5895,7 @@ int RM_HashGet(RedisModuleKey *key, int flags, ...) {
*existsptr = 0;
}
} else if (flags & REDISMODULE_HASH_EXPIRE_TIME) {
mstime_t *expireptr = va_arg(ap,mstime_t*);
mstime_t *expireptr = va_arg(ap,mstime_t*);
*expireptr = REDISMODULE_NO_EXPIRE;
if (key->kv) {
uint64_t expireTime = 0;
@ -5932,7 +5932,7 @@ int RM_HashGet(RedisModuleKey *key, int flags, ...) {
/**
* Retrieves the minimum expiration time of fields in a hash.
*
*
* Return:
* - The minimum expiration time (in milliseconds) of the hash fields if at
* least one field has an expiration set.
@ -5942,7 +5942,7 @@ int RM_HashGet(RedisModuleKey *key, int flags, ...) {
mstime_t RM_HashFieldMinExpire(RedisModuleKey *key) {
if ((!key->kv) || (key->kv->type != OBJ_HASH))
return REDISMODULE_NO_EXPIRE;
mstime_t min = hashTypeGetMinExpire(key->kv, 1);
return (min == EB_EXPIRE_TIME_INVALID) ? REDISMODULE_NO_EXPIRE : min;
}
@ -7367,7 +7367,7 @@ robj *moduleTypeDupOrReply(client *c, robj *fromkey, robj *tokey, int todb, robj
} else {
newval = mt->copy(fromkey, tokey, mv->value);
}
if (!newval) {
addReplyError(c, "module key failed to copy");
return NULL;
@ -7417,7 +7417,7 @@ robj *moduleTypeDupOrReply(client *c, robj *fromkey, robj *tokey, int todb, robj
* .unlink = myType_UnlinkCallBack,
* .copy = myType_CopyCallback,
* .defrag = myType_DefragCallback
*
*
* // Enhanced optional fields
* .mem_usage2 = myType_MemUsageCallBack2,
* .free_effort2 = myType_FreeEffortCallBack2,
@ -7436,11 +7436,11 @@ robj *moduleTypeDupOrReply(client *c, robj *fromkey, robj *tokey, int todb, robj
* Similar to aux_save, returns REDISMODULE_OK on success, and ERR otherwise.
* * **free_effort**: A callback function pointer that used to determine whether the module's
* memory needs to be lazy reclaimed. The module should return the complexity involved by
* freeing the value. for example: how many pointers are gonna be freed. Note that if it
* freeing the value. for example: how many pointers are gonna be freed. Note that if it
* returns 0, we'll always do an async free.
* * **unlink**: A callback function pointer that used to notifies the module that the key has
* been removed from the DB by redis, and may soon be freed by a background thread. Note that
* it won't be called on FLUSHALL/FLUSHDB (both sync and async), and the module can use the
* * **unlink**: A callback function pointer that used to notifies the module that the key has
* been removed from the DB by redis, and may soon be freed by a background thread. Note that
* it won't be called on FLUSHALL/FLUSHDB (both sync and async), and the module can use the
* RedisModuleEvent_FlushDB to hook into that.
* * **copy**: A callback function pointer that is used to make a copy of the specified key.
* The module is expected to perform a deep copy of the specified value and return it.
@ -7448,7 +7448,7 @@ robj *moduleTypeDupOrReply(client *c, robj *fromkey, robj *tokey, int todb, robj
* A NULL return value is considered an error and the copy operation fails.
* Note: if the target key exists and is being overwritten, the copy callback will be
* called first, followed by a free callback to the value that is being replaced.
*
*
* * **defrag**: A callback function pointer that is used to request the module to defrag
* a key. The module should then iterate pointers and call the relevant RM_Defrag*()
* functions to defragment pointers or complex types. The module should continue
@ -7476,7 +7476,7 @@ robj *moduleTypeDupOrReply(client *c, robj *fromkey, robj *tokey, int todb, robj
* * **aux_save2**: Similar to `aux_save`, but with small semantic change, if the module
* saves nothing on this callback then no data about this aux field will be written to the
* RDB and it will be possible to load the RDB even if the module is not loaded.
*
*
* Note: the module name "AAAAAAAAA" is reserved and produces an error, it
* happens to be pretty lame as well.
*
@ -8033,7 +8033,7 @@ void *RM_LoadDataTypeFromStringEncver(const RedisModuleString *str, const module
void *ret;
rioInitWithBuffer(&payload, str->ptr);
moduleType *mt_non_const = (moduleType *)mt; /*cast const away*/
moduleType *mt_non_const = (moduleType *)mt; /*cast const away*/
moduleInitIOContext(&io, &mt_non_const->entity, &payload, NULL, -1);
/* All RM_Save*() calls always write a version 2 compatible format, so we
@ -8048,7 +8048,7 @@ void *RM_LoadDataTypeFromStringEncver(const RedisModuleString *str, const module
}
/* Similar to RM_LoadDataTypeFromStringEncver, original version of the API, kept
* for backward compatibility.
* for backward compatibility.
*/
void *RM_LoadDataTypeFromString(const RedisModuleString *str, const moduleType *mt) {
return RM_LoadDataTypeFromStringEncver(str, mt, 0);
@ -8999,7 +8999,7 @@ int moduleBlockedClientMayTimeout(client *c) {
/* Called when our client timed out. After this function unblockClient()
* is called, and it will invalidate the blocked client. So this function
* does not need to do any cleanup. Eventually the module will call the
* API to unblock the client and the memory will be released.
* API to unblock the client and the memory will be released.
*
* This function should only be called from the main thread, we must handle the unblocking
* of the client synchronously. This ensures that we can reply to the client before
@ -9603,6 +9603,14 @@ int RM_AddPostNotificationJobForKey(RedisModuleCtx *ctx, RedisModulePostNotifica
return REDISMODULE_ERR;
}
if (!callback || !key) {
serverLog(LL_WARNING,
"API misuse detected in module %s: "
"RedisModule_AddPostNotificationJobForKey called with NULL callback or key.",
ctx->module->name);
return REDISMODULE_ERR;
}
RedisModulePostKeyedNotificationJob *job = zmalloc(sizeof(*job));
job->module = ctx->module;
job->callback = callback;
@ -10631,9 +10639,9 @@ int RM_FreeModuleUser(RedisModuleUser *user) {
* The returned string must be freed by the caller with RedisModule_FreeString()
* or by enabling automatic memory management on a context. */
RedisModuleString *RM_GetUserUsername(RedisModuleCtx *ctx, const RedisModuleUser *user) {
if(user == NULL || user->user == NULL || user->user->name == NULL)
if(user == NULL || user->user == NULL || user->user->name == NULL)
return NULL;
return RM_CreateString(ctx, user->user->name, sdslen(user->user->name));
}
@ -10765,13 +10773,13 @@ int RM_ACLCheckCommandPermissions(RedisModuleUser *user, RedisModuleString **arg
* keyspec for logical operations. These flags are documented in RedisModule_SetCommandInfo as
* the REDISMODULE_CMD_KEY_ACCESS, REDISMODULE_CMD_KEY_UPDATE, REDISMODULE_CMD_KEY_INSERT,
* and REDISMODULE_CMD_KEY_DELETE flags.
*
*
* If no flags are supplied, the user is still required to have some access to the key for
* this command to return successfully.
*
* If the user is able to access the key then REDISMODULE_OK is returned, otherwise
* REDISMODULE_ERR is returned and errno is set to one of the following values:
*
*
* * EINVAL: The provided flags are invalid.
* * EACCESS: The user does not have permission to access the key.
*/
@ -10795,18 +10803,18 @@ int RM_ACLCheckKeyPermissions(RedisModuleUser *user, RedisModuleString *key, int
return REDISMODULE_OK;
}
/* Check if the user can access keys matching the given key prefix according to the ACLs
* attached to the user and the flags representing key access. The flags are the same that
* are used in the keyspec for logical operations. These flags are documented in
* RedisModule_SetCommandInfo as the REDISMODULE_CMD_KEY_ACCESS,
/* Check if the user can access keys matching the given key prefix according to the ACLs
* attached to the user and the flags representing key access. The flags are the same that
* are used in the keyspec for logical operations. These flags are documented in
* RedisModule_SetCommandInfo as the REDISMODULE_CMD_KEY_ACCESS,
* REDISMODULE_CMD_KEY_UPDATE, REDISMODULE_CMD_KEY_INSERT, and REDISMODULE_CMD_KEY_DELETE flags.
*
* If no flags are supplied, the user is still required to have some access to keys matching
*
* If no flags are supplied, the user is still required to have some access to keys matching
* the prefix for this command to return successfully.
*
* If the user is able to access keys matching the prefix, then REDISMODULE_OK is returned.
* Otherwise, REDISMODULE_ERR is returned and errno is set to one of the following values:
*
*
* * EINVAL: The provided flags are invalid.
* * EACCES: The user does not have permission to access keys matching the prefix.
*/
@ -10840,9 +10848,9 @@ int RM_ACLCheckKeyPrefixPermissions(RedisModuleUser *user, RedisModuleString *pr
*
* If the user is able to access the pubsub channel then REDISMODULE_OK is returned, otherwise
* REDISMODULE_ERR is returned and errno is set to one of the following values:
*
*
* * EINVAL: The provided flags are invalid.
* * EACCESS: The user does not have permission to access the pubsub channel.
* * EACCESS: The user does not have permission to access the pubsub channel.
*/
int RM_ACLCheckChannelPermissions(RedisModuleUser *user, RedisModuleString *ch, int flags) {
const int allow_mask = (REDISMODULE_CMD_CHANNEL_PUBLISH
@ -11000,15 +11008,15 @@ int RM_DeauthenticateAndCloseClient(RedisModuleCtx *ctx, uint64_t client_id) {
return REDISMODULE_OK;
}
/* Redact the client command argument specified at the given position. Redacted arguments
/* Redact the client command argument specified at the given position. Redacted arguments
* are obfuscated in user facing commands such as SLOWLOG or MONITOR, as well as
* never being written to server logs. This command may be called multiple times on the
* same position.
*
* Note that the command name, position 0, can not be redacted.
*
* Returns REDISMODULE_OK if the argument was redacted and REDISMODULE_ERR if there
* was an invalid parameter passed in or the position is outside the client
*
* Note that the command name, position 0, can not be redacted.
*
* Returns REDISMODULE_OK if the argument was redacted and REDISMODULE_ERR if there
* was an invalid parameter passed in or the position is outside the client
* argument range. */
int RM_RedactClientCommandArgument(RedisModuleCtx *ctx, int pos) {
if (!ctx || !ctx->client || pos <= 0 || ctx->client->argc <= pos) {
@ -12199,7 +12207,7 @@ static void moduleScanKeyCallback(void *privdata, const dictEntry *de, dictEntry
field = createStringObject(fieldStr, sdslen(fieldStr));
value = createStringObjectFromLongDouble(znode->score, 0);
}
serverAssert(field != NULL);
data->fn(data->key, field, value, data->user_data);
decrRefCount(field);
@ -12687,7 +12695,7 @@ static uint64_t moduleEventVersions[] = {
* int32_t dbnum_second; // Swap Db second dbnum
*
* * RedisModuleEvent_ReplBackup
*
*
* WARNING: Replication Backup events are deprecated since Redis 7.0 and are never fired.
* See RedisModuleEvent_ReplAsyncLoad for understanding how Async Replication Loading events
* are now triggered when repl-diskless-load is set to swapdb.
@ -12702,7 +12710,7 @@ static uint64_t moduleEventVersions[] = {
* * `REDISMODULE_SUBEVENT_REPL_BACKUP_CREATE`
* * `REDISMODULE_SUBEVENT_REPL_BACKUP_RESTORE`
* * `REDISMODULE_SUBEVENT_REPL_BACKUP_DISCARD`
*
*
* * RedisModuleEvent_ReplAsyncLoad
*
* Called when repl-diskless-load config is set to swapdb and a replication with a master of same
@ -12744,7 +12752,7 @@ static uint64_t moduleEventVersions[] = {
* structure with the following fields:
*
* const char **config_names; // An array of C string pointers containing the
* // name of each modified configuration item
* // name of each modified configuration item
* uint32_t num_changes; // The number of elements in the config_names array
*
* * RedisModule_Event_Key
@ -12898,7 +12906,7 @@ int RM_IsSubEventSupported(RedisModuleEvent event, int64_t subevent) {
case REDISMODULE_EVENT_EVENTLOOP:
return subevent < _REDISMODULE_SUBEVENT_EVENTLOOP_NEXT;
case REDISMODULE_EVENT_CONFIG:
return subevent < _REDISMODULE_SUBEVENT_CONFIG_NEXT;
return subevent < _REDISMODULE_SUBEVENT_CONFIG_NEXT;
case REDISMODULE_EVENT_KEY:
return subevent < _REDISMODULE_SUBEVENT_KEY_NEXT;
case REDISMODULE_EVENT_CLUSTER_SLOT_MIGRATION:
@ -13080,7 +13088,7 @@ void moduleNotifyKeyUnlink(robj *key, kvobj *kv, int dbid, int flags) {
server.allow_access_trimmed--;
}
/* Return the free_effort of the module, it will automatically choose to call
/* Return the free_effort of the module, it will automatically choose to call
* `free_effort` or `free_effort2`, and the default return value is 1.
* value of 0 means very high effort (always asynchronous freeing). */
size_t moduleGetFreeEffort(robj *key, robj *val, int dbid) {
@ -13093,12 +13101,12 @@ size_t moduleGetFreeEffort(robj *key, robj *val, int dbid) {
effort = mt->free_effort2(&ctx,mv->value);
} else if (mt->free_effort != NULL) {
effort = mt->free_effort(key,mv->value);
}
}
return effort;
}
/* Return the memory usage of the module, it will automatically choose to call
/* Return the memory usage of the module, it will automatically choose to call
* `mem_usage` or `mem_usage2`, and the default return value is 0. */
size_t moduleGetMemUsage(robj *key, robj *val, size_t sample_size, int dbid) {
moduleValue *mv = val->ptr;
@ -13110,7 +13118,7 @@ size_t moduleGetMemUsage(robj *key, robj *val, size_t sample_size, int dbid) {
size = mt->mem_usage2(&ctx, mv->value, sample_size);
} else if (mt->mem_usage != NULL) {
size = mt->mem_usage(mv->value);
}
}
return size;
}
@ -13582,7 +13590,7 @@ int moduleOnLoad(int (*onload)(void *, void **, int), const char *path, void *ha
/* Unload the module registered with the specified name. On success
* C_OK is returned, otherwise C_ERR is returned and errmsg is set
* with an appropriate message.
* Only forcefully unload this module, passing forced_unload != 0,
* Only forcefully unload this module, passing forced_unload != 0,
* if it is certain that it has not yet been in use (e.g., immediate
* unload on failed load). */
int moduleUnload(sds name, const char **errmsg, int forced_unload) {
@ -13765,7 +13773,7 @@ sds genModulesInfoString(sds info) {
/* --------------------------------------------------------------------------
* Module Configurations API internals
* -------------------------------------------------------------------------- */
/* Check if the configuration name is already registered */
int isModuleConfigNameRegistered(RedisModule *module, const char *name) {
listNode *match = listSearchKey(module->module_configs, (void *) name);
@ -13819,11 +13827,11 @@ int moduleVerifyResourceName(const char *name) {
return REDISMODULE_OK;
}
/* Verify unprefixed name config might be a single "<name>" or in the form
* "<name>|<alias>". Unlike moduleVerifyResourceName(), unprefixed name config
* allows a single dot in the name or alias.
*
* delim - Updates to point to "|" if it exists, NULL otherwise.
/* Verify unprefixed name config might be a single "<name>" or in the form
* "<name>|<alias>". Unlike moduleVerifyResourceName(), unprefixed name config
* allows a single dot in the name or alias.
*
* delim - Updates to point to "|" if it exists, NULL otherwise.
*/
int moduleVerifyUnprefixedName(const char *nameAlias, const char **delim) {
if (nameAlias[0] == '\0')
@ -13834,7 +13842,7 @@ int moduleVerifyUnprefixedName(const char *nameAlias, const char **delim) {
for (size_t i = 0; nameAlias[i] != '\0'; i++) {
char ch = nameAlias[i];
if (((*delim) == NULL) && (ch == '|')) {
/* Handle single separator between name and alias */
if (!lname) {
@ -13849,7 +13857,7 @@ int moduleVerifyUnprefixedName(const char *nameAlias, const char **delim) {
++lname;
} else if (ch == '.') {
/* Allow only one dot per section (name or alias) */
if (++dot_count > 1) {
if (++dot_count > 1) {
serverLog(LL_WARNING, "Invalid character sequence in Module configuration name or alias: %s", nameAlias);
return REDISMODULE_ERR;
}
@ -13858,7 +13866,7 @@ int moduleVerifyUnprefixedName(const char *nameAlias, const char **delim) {
return REDISMODULE_ERR;
}
}
if (!lname) {
serverLog(LL_WARNING, "Module configuration name or alias is empty : %s", nameAlias);
return REDISMODULE_ERR;
@ -13867,7 +13875,7 @@ int moduleVerifyUnprefixedName(const char *nameAlias, const char **delim) {
return REDISMODULE_OK;
}
/* This is a series of set functions for each type that act as dispatchers for
/* This is a series of set functions for each type that act as dispatchers for
* config.c to call module set callbacks. */
#define CONFIG_ERR_SIZE 256
static char configerr[CONFIG_ERR_SIZE];
@ -13879,8 +13887,8 @@ static void propagateErrorString(RedisModuleString *err_in, const char **err) {
}
}
/* If configuration was originally registered with indication to prefix the name,
* return the name without the prefix by skipping prefix "<MODULE-NAME>.".
/* If configuration was originally registered with indication to prefix the name,
* return the name without the prefix by skipping prefix "<MODULE-NAME>.".
* Otherwise, return the stored name as is. */
static char *getRegisteredConfigName(ModuleConfig *config) {
if (config->unprefixedFlag)
@ -13888,7 +13896,7 @@ static char *getRegisteredConfigName(ModuleConfig *config) {
/* For prefixed configuration, find the '.' indicating the end of the prefix */
char *endOfPrefix = strchr(config->name, '.');
serverAssert(endOfPrefix != NULL);
serverAssert(endOfPrefix != NULL);
return endOfPrefix + 1;
}
@ -13904,7 +13912,7 @@ int setModuleBoolConfig(ModuleConfig *config, int val, const char **err) {
int setModuleStringConfig(ModuleConfig *config, sds strval, const char **err) {
RedisModuleString *error = NULL;
RedisModuleString *new = createStringObject(strval, sdslen(strval));
char *rname = getRegisteredConfigName(config);
int return_code = config->set_fn.set_string(rname, new, config->privdata, &error);
propagateErrorString(error, err);
@ -13928,7 +13936,7 @@ int setModuleNumericConfig(ModuleConfig *config, long long val, const char **err
return return_code == REDISMODULE_OK ? 1 : 0;
}
/* This is a series of get functions for each type that act as dispatchers for
/* This is a series of get functions for each type that act as dispatchers for
* config.c to call module set callbacks. */
int getModuleBoolConfig(ModuleConfig *module_config) {
char *rname = getRegisteredConfigName(module_config);
@ -14067,19 +14075,19 @@ int moduleConfigApplyConfig(list *module_configs, const char **err, const char *
* -------------------------------------------------------------------------- */
/* Resolve config name and create a module config object */
ModuleConfig *createModuleConfig(const char *name, RedisModuleConfigApplyFunc apply_fn,
void *privdata, RedisModule *module, unsigned int flags)
ModuleConfig *createModuleConfig(const char *name, RedisModuleConfigApplyFunc apply_fn,
void *privdata, RedisModule *module, unsigned int flags)
{
sds cname, alias = NULL;
/* Determine the configuration name:
* - If the unprefixed flag is set, the "<MODULE-NAME>." prefix is omitted.
* - An optional alias can be specified using "<NAME>|<ALIAS>".
*
*
* Examples:
* - Unprefixed: "bf.initial_size" or "bf-initial-size|bf.initial_size".
* - Prefixed: "initial_size" becomes "<MODULE-NAME>.initial_size".
*/
*/
if (flags & REDISMODULE_CONFIG_UNPREFIXED) {
const char *delim = strchr(name, '|');
cname = sdsnew(name);
@ -14091,7 +14099,7 @@ ModuleConfig *createModuleConfig(const char *name, RedisModuleConfigApplyFunc ap
/* Add the module name prefix */
cname = sdscatfmt(sdsempty(), "%s.%s", module->name, name);
}
ModuleConfig *new_config = zmalloc(sizeof(ModuleConfig));
new_config->unprefixedFlag = flags & REDISMODULE_CONFIG_UNPREFIXED;
new_config->name = cname;
@ -14103,7 +14111,7 @@ ModuleConfig *createModuleConfig(const char *name, RedisModuleConfigApplyFunc ap
}
/* Verify the configuration name and check for duplicates.
*
*
* - If the configuration is flagged as unprefixed, it checks for duplicate
* names and optional aliases in the format <NAME>|<ALIAS>.
* - If the configuration is prefixed, it ensures the name is unique with
@ -14118,22 +14126,22 @@ int moduleConfigValidityCheck(RedisModule *module, const char *name, unsigned in
errno = EINVAL;
return REDISMODULE_ERR;
}
int isdup = 0;
int isdup = 0;
if (flags & REDISMODULE_CONFIG_UNPREFIXED) {
const char *delim = NULL; /* Pointer to the '|' delimiter in <NAME>|<ALIAS> */
if (moduleVerifyUnprefixedName(name, &delim)){
errno = EINVAL;
return REDISMODULE_ERR;
}
if (delim) {
if (delim) {
/* Temporary split the "<NAME>|<ALIAS>" for the check */
int count;
sds *ar = sdssplitlen(name, strlen(name), "|", 1, &count);
serverAssert(count == 2); /* Already validated */
isdup = configExists(ar[0]) ||
configExists(ar[1]) ||
isdup = configExists(ar[0]) ||
configExists(ar[1]) ||
(sdscmp(ar[0], ar[1]) == 0);
sdsfreesplitres(ar, count);
} else {
@ -14151,7 +14159,7 @@ int moduleConfigValidityCheck(RedisModule *module, const char *name, unsigned in
isdup = configExists(fullname);
sdsfree(fullname);
}
if (isdup) {
serverLog(LL_WARNING, "Configuration by the name: %s already registered", name);
errno = EALREADY;
@ -14262,19 +14270,19 @@ int RM_RegisterStringConfig(RedisModuleCtx *ctx, const char *name, const char *d
if (moduleConfigValidityCheck(module, name, flags, NUMERIC_CONFIG)) {
return REDISMODULE_ERR;
}
ModuleConfig *mc = createModuleConfig(name, applyfn, privdata, module, flags);
mc->get_fn.get_string = getfn;
mc->set_fn.set_string = setfn;
listAddNodeTail(module->module_configs, mc);
unsigned int cflags = maskModuleConfigFlags(flags);
addModuleStringConfig(sdsdup(mc->name), (mc->alias) ? sdsdup(mc->alias) : NULL,
addModuleStringConfig(sdsdup(mc->name), (mc->alias) ? sdsdup(mc->alias) : NULL,
cflags, mc, default_val ? sdsnew(default_val) : NULL);
return REDISMODULE_OK;
}
/* Create a bool config that server clients can interact with via the
* `CONFIG SET`, `CONFIG GET`, and `CONFIG REWRITE` commands. See
/* Create a bool config that server clients can interact with via the
* `CONFIG SET`, `CONFIG GET`, and `CONFIG REWRITE` commands. See
* RedisModule_RegisterStringConfig for detailed information about configs. */
int RM_RegisterBoolConfig(RedisModuleCtx *ctx, const char *name, int default_val, unsigned int flags, RedisModuleConfigGetBoolFunc getfn, RedisModuleConfigSetBoolFunc setfn, RedisModuleConfigApplyFunc applyfn, void *privdata) {
RedisModule *module = ctx->module;
@ -14286,15 +14294,15 @@ int RM_RegisterBoolConfig(RedisModuleCtx *ctx, const char *name, int default_val
mc->set_fn.set_bool = setfn;
listAddNodeTail(module->module_configs, mc);
unsigned int cflags = maskModuleConfigFlags(flags);
addModuleBoolConfig(sdsdup(mc->name), (mc->alias) ? sdsdup(mc->alias) : NULL,
addModuleBoolConfig(sdsdup(mc->name), (mc->alias) ? sdsdup(mc->alias) : NULL,
cflags, mc, default_val);
return REDISMODULE_OK;
}
/*
* Create an enum config that server clients can interact with via the
* `CONFIG SET`, `CONFIG GET`, and `CONFIG REWRITE` commands.
* Enum configs are a set of string tokens to corresponding integer values, where
/*
* Create an enum config that server clients can interact with via the
* `CONFIG SET`, `CONFIG GET`, and `CONFIG REWRITE` commands.
* Enum configs are a set of string tokens to corresponding integer values, where
* the string value is exposed to Redis clients but the value passed Redis and the
* module is the integer value. These values are defined in enum_values, an array
* of null-terminated c strings, and int_vals, an array of enum values who has an
@ -14307,7 +14315,7 @@ int RM_RegisterBoolConfig(RedisModuleCtx *ctx, const char *name, int default_val
* int getEnumConfigCommand(const char *name, void *privdata) {
* return enum_val;
* }
*
*
* int setEnumConfigCommand(const char *name, int val, void *privdata, const char **err) {
* enum_val = val;
* return REDISMODULE_OK;
@ -14338,14 +14346,14 @@ int RM_RegisterEnumConfig(RedisModuleCtx *ctx, const char *name, int default_val
listAddNodeTail(module->module_configs, mc);
unsigned int cflags = maskModuleConfigFlags(flags) | maskModuleEnumConfigFlags(flags);
addModuleEnumConfig(sdsdup(mc->name), (mc->alias) ? sdsdup(mc->alias) : NULL,
addModuleEnumConfig(sdsdup(mc->name), (mc->alias) ? sdsdup(mc->alias) : NULL,
cflags, mc, default_val, enum_vals, num_enum_vals);
return REDISMODULE_OK;
}
/*
* Create an integer config that server clients can interact with via the
* `CONFIG SET`, `CONFIG GET`, and `CONFIG REWRITE` commands. See
* Create an integer config that server clients can interact with via the
* `CONFIG SET`, `CONFIG GET`, and `CONFIG REWRITE` commands. See
* RedisModule_RegisterStringConfig for detailed information about configs. */
int RM_RegisterNumericConfig(RedisModuleCtx *ctx, const char *name, long long default_val, unsigned int flags, long long min, long long max, RedisModuleConfigGetNumericFunc getfn, RedisModuleConfigSetNumericFunc setfn, RedisModuleConfigApplyFunc applyfn, void *privdata) {
RedisModule *module = ctx->module;
@ -14359,7 +14367,7 @@ int RM_RegisterNumericConfig(RedisModuleCtx *ctx, const char *name, long long de
unsigned int numeric_flags = maskModuleNumericConfigFlags(flags);
unsigned int cflags = maskModuleConfigFlags(flags);
addModuleNumericConfig(sdsdup(mc->name), (mc->alias) ? sdsdup(mc->alias) : NULL,
addModuleNumericConfig(sdsdup(mc->name), (mc->alias) ? sdsdup(mc->alias) : NULL,
cflags, mc, default_val, numeric_flags, min, max);
return REDISMODULE_OK;
}
@ -14867,7 +14875,7 @@ NULL
argc = c->argc - 3;
argv = &c->argv[3];
}
/* If this is a loadex command we want to populate server.module_configs_queue with
/* If this is a loadex command we want to populate server.module_configs_queue with
* sds NAME VALUE pairs. We also want to increment argv to just after ARGS, if supplied. */
if (parseLoadexArguments((RedisModuleString ***) &argv, &argc) == REDISMODULE_OK &&
moduleLoad(c->argv[2]->ptr, (void **)argv, argc, 1) == C_OK)
@ -15272,8 +15280,8 @@ void *RM_DefragAlloc(RedisModuleDefragCtx *ctx, void *ptr) {
* owner. For such usecase RM_DefragAlloc is enough. But on some usecases the user
* might want to replace a pointer with multiple owners in different keys.
* In such case, an in place replacement can not work because the other key still
* keep a pointer to the old value.
*
* keep a pointer to the old value.
*
* RM_DefragAllocRaw and RM_DefragFreeRaw allows to control when the memory
* for defrag purposes will be allocated and when it will be freed,
* allow to support more complex defrag usecases. */
@ -15283,7 +15291,7 @@ void *RM_DefragAllocRaw(RedisModuleDefragCtx *ctx, size_t size) {
}
/* Free memory for defrag purposes
*
*
* See RM_DefragAllocRaw for more information. */
void RM_DefragFreeRaw(RedisModuleDefragCtx *ctx, void *ptr) {
UNUSED(ctx);
@ -15459,7 +15467,7 @@ int moduleDefragValue(robj *key, robj *value, int dbid) {
/* Call registered module API defrag start functions */
void moduleDefragStart(void) {
dictForEach(modules, struct RedisModule, module,
dictForEach(modules, struct RedisModule, module,
if (module->defrag_start_cb) {
RedisModuleDefragCtx defrag_ctx = INIT_MODULE_DEFRAG_CTX(0, NULL, NULL, -1);
module->defrag_start_cb(&defrag_ctx);
@ -15469,7 +15477,7 @@ void moduleDefragStart(void) {
/* Call registered module API defrag end functions */
void moduleDefragEnd(void) {
dictForEach(modules, struct RedisModule, module,
dictForEach(modules, struct RedisModule, module,
if (module->defrag_end_cb) {
RedisModuleDefragCtx defrag_ctx = INIT_MODULE_DEFRAG_CTX(0, NULL, NULL, -1);
module->defrag_end_cb(&defrag_ctx);

View file

@ -78,7 +78,7 @@ foreach api {regular perkey} {
[r keys expired] == {expired}
} else {
puts [r keys *]
fail "Failed waiting for x to expired"
fail "Failed waiting for x to expire"
}
# {lpush before_expired x} comes from the RedisModuleEvent_Key