{
  "id": "modules-api-ref",
  "title": "Modules API reference",
  "url": "https://un5pn9hmggug.julianrbryant.com/docs/latest/develop/reference/modules/modules-api-ref/",
  "summary": "Reference for the Redis Modules API",
  "tags": [
    "docs",
    "develop",
    "stack",
    "oss",
    "rs",
    "rc",
    "oss",
    "kubernetes",
    "clients"
  ],
  "last_updated": "2026-04-01T08:10:08-05:00",
  "page_type": "content",
  "content_hash": "fc6b5744543b8433e1204ec230683b615c52df2b64e8ba06bdef8f65870c9a55",
  "sections": [
    {
      "id": "overview",
      "title": "Overview",
      "role": "overview",
      "text": "<!-- This file is generated from module.c using\n     redis/redis:utils/generate-module-api-doc.rb -->"
    },
    {
      "id": "sections",
      "title": "Sections",
      "role": "content",
      "text": "* [Heap allocation raw functions](#section-heap-allocation-raw-functions)\n* [Commands API](#section-commands-api)\n* [Module information and time measurement](#section-module-information-and-time-measurement)\n* [Automatic memory management for modules](#section-automatic-memory-management-for-modules)\n* [String objects APIs](#section-string-objects-apis)\n* [Reply APIs](#section-reply-apis)\n* [Commands replication API](#section-commands-replication-api)\n* [DB and Key APIs – Generic API](#section-db-and-key-apis-generic-api)\n* [Key API for String type](#section-key-api-for-string-type)\n* [Key API for List type](#section-key-api-for-list-type)\n* [Key API for Sorted Set type](#section-key-api-for-sorted-set-type)\n* [Key API for Sorted Set iterator](#section-key-api-for-sorted-set-iterator)\n* [Key API for Hash type](#section-key-api-for-hash-type)\n* [Key API for Stream type](#section-key-api-for-stream-type)\n* [Calling Redis commands from modules](#section-calling-redis-commands-from-modules)\n* [Modules data types](#section-modules-data-types)\n* [RDB loading and saving functions](#section-rdb-loading-and-saving-functions)\n* [Key digest API (DEBUG DIGEST interface for modules types)](#section-key-digest-api-debug-digest-interface-for-modules-types)\n* [AOF API for modules data types](#section-aof-api-for-modules-data-types)\n* [IO context handling](#section-io-context-handling)\n* [Logging](#section-logging)\n* [Blocking clients from modules](#section-blocking-clients-from-modules)\n* [Thread Safe Contexts](#section-thread-safe-contexts)\n* [Module Keyspace Notifications API](#section-module-keyspace-notifications-api)\n* [Modules Cluster API](#section-modules-cluster-api)\n* [Modules Timers API](#section-modules-timers-api)\n* [Modules EventLoop API](#section-modules-eventloop-api)\n* [Modules ACL API](#section-modules-acl-api)\n* [Modules Dictionary API](#section-modules-dictionary-api)\n* [Modules Info fields](#section-modules-info-fields)\n* [Modules utility APIs](#section-modules-utility-apis)\n* [Modules API exporting / importing](#section-modules-api-exporting-importing)\n* [Module Command Filter API](#section-module-command-filter-api)\n* [Scanning keyspace and hashes](#section-scanning-keyspace-and-hashes)\n* [Module fork API](#section-module-fork-api)\n* [Server hooks implementation](#section-server-hooks-implementation)\n* [Module Configurations API](#section-module-configurations-api)\n* [RDB load/save API](#section-rdb-load-save-api)\n* [Config access API](#section-config-access-api)\n* [Key eviction API](#section-key-eviction-api)\n* [Miscellaneous APIs](#section-miscellaneous-apis)\n* [Defrag API](#section-defrag-api)\n* [Function index](#section-function-index)\n\n<span id=\"section-heap-allocation-raw-functions\"></span>"
    },
    {
      "id": "heap-allocation-raw-functions",
      "title": "Heap allocation raw functions",
      "role": "content",
      "text": "Memory allocated with these functions are taken into account by Redis key\neviction algorithms and are reported in Redis memory usage information.\n\n<span id=\"RedisModule_Alloc\"></span>"
    },
    {
      "id": "redismodule-alloc",
      "title": "`RedisModule_Alloc`",
      "role": "content",
      "text": "void *RedisModule_Alloc(size_t bytes);\n\n**Available since:** 4.0.0\n\nUse like `malloc()`. Memory allocated with this function is reported in\nRedis INFO memory, used for keys eviction according to maxmemory settings\nand in general is taken into account as memory allocated by Redis.\nYou should avoid using `malloc()`.\nThis function panics if unable to allocate enough memory.\n\n<span id=\"RedisModule_TryAlloc\"></span>"
    },
    {
      "id": "redismodule-tryalloc",
      "title": "`RedisModule_TryAlloc`",
      "role": "content",
      "text": "void *RedisModule_TryAlloc(size_t bytes);\n\n**Available since:** 7.0.0\n\nSimilar to [`RedisModule_Alloc`](#RedisModule_Alloc), but returns NULL in case of allocation failure, instead\nof panicking.\n\n<span id=\"RedisModule_Calloc\"></span>"
    },
    {
      "id": "redismodule-calloc",
      "title": "`RedisModule_Calloc`",
      "role": "content",
      "text": "void *RedisModule_Calloc(size_t nmemb, size_t size);\n\n**Available since:** 4.0.0\n\nUse like `calloc()`. Memory allocated with this function is reported in\nRedis INFO memory, used for keys eviction according to maxmemory settings\nand in general is taken into account as memory allocated by Redis.\nYou should avoid using `calloc()` directly.\n\n<span id=\"RedisModule_TryCalloc\"></span>"
    },
    {
      "id": "redismodule-trycalloc",
      "title": "`RedisModule_TryCalloc`",
      "role": "content",
      "text": "void *RedisModule_TryCalloc(size_t nmemb, size_t size);\n\n**Available since:** 7.4.0\n\nSimilar to [`RedisModule_Calloc`](#RedisModule_Calloc), but returns NULL in case of allocation failure, instead\nof panicking.\n\n<span id=\"RedisModule_Realloc\"></span>"
    },
    {
      "id": "redismodule-realloc",
      "title": "`RedisModule_Realloc`",
      "role": "content",
      "text": "void* RedisModule_Realloc(void *ptr, size_t bytes);\n\n**Available since:** 4.0.0\n\nUse like `realloc()` for memory obtained with [`RedisModule_Alloc()`](#RedisModule_Alloc).\n\n<span id=\"RedisModule_TryRealloc\"></span>"
    },
    {
      "id": "redismodule-tryrealloc",
      "title": "`RedisModule_TryRealloc`",
      "role": "content",
      "text": "void *RedisModule_TryRealloc(void *ptr, size_t bytes);\n\n**Available since:** 7.4.0\n\nSimilar to [`RedisModule_Realloc`](#RedisModule_Realloc), but returns NULL in case of allocation failure,\ninstead of panicking.\n\n<span id=\"RedisModule_Free\"></span>"
    },
    {
      "id": "redismodule-free",
      "title": "`RedisModule_Free`",
      "role": "content",
      "text": "void RedisModule_Free(void *ptr);\n\n**Available since:** 4.0.0\n\nUse like `free()` for memory obtained by [`RedisModule_Alloc()`](#RedisModule_Alloc) and\n[`RedisModule_Realloc()`](#RedisModule_Realloc). However you should never try to free with\n[`RedisModule_Free()`](#RedisModule_Free) memory allocated with `malloc()` inside your module.\n\n<span id=\"RedisModule_Strdup\"></span>"
    },
    {
      "id": "redismodule-strdup",
      "title": "`RedisModule_Strdup`",
      "role": "content",
      "text": "char *RedisModule_Strdup(const char *str);\n\n**Available since:** 4.0.0\n\nLike `strdup()` but returns memory allocated with [`RedisModule_Alloc()`](#RedisModule_Alloc).\n\n<span id=\"RedisModule_PoolAlloc\"></span>"
    },
    {
      "id": "redismodule-poolalloc",
      "title": "`RedisModule_PoolAlloc`",
      "role": "content",
      "text": "void *RedisModule_PoolAlloc(RedisModuleCtx *ctx, size_t bytes);\n\n**Available since:** 4.0.0\n\nReturn heap allocated memory that will be freed automatically when the\nmodule callback function returns. Mostly suitable for small allocations\nthat are short living and must be released when the callback returns\nanyway. The returned memory is aligned to the architecture word size\nif at least word size bytes are requested, otherwise it is just\naligned to the next power of two, so for example a 3 bytes request is\n4 bytes aligned while a 2 bytes request is 2 bytes aligned.\n\nThere is no realloc style function since when this is needed to use the\npool allocator is not a good idea.\n\nThe function returns NULL if `bytes` is 0.\n\n<span id=\"section-commands-api\"></span>"
    },
    {
      "id": "commands-api",
      "title": "Commands API",
      "role": "syntax",
      "text": "These functions are used to implement custom Redis commands.\n\nFor examples, see [https://un5pn9hmggug.julianrbryant.com/docs/latest/develop/reference/modules/](https://un5pn9hmggug.julianrbryant.com/docs/latest/develop/reference/modules/).\n\n<span id=\"RedisModule_IsKeysPositionRequest\"></span>"
    },
    {
      "id": "redismodule-iskeyspositionrequest",
      "title": "`RedisModule_IsKeysPositionRequest`",
      "role": "content",
      "text": "int RedisModule_IsKeysPositionRequest(RedisModuleCtx *ctx);\n\n**Available since:** 4.0.0\n\nReturn non-zero if a module command, that was declared with the\nflag \"getkeys-api\", is called in a special way to get the keys positions\nand not to get executed. Otherwise zero is returned.\n\n<span id=\"RedisModule_KeyAtPosWithFlags\"></span>"
    },
    {
      "id": "redismodule-keyatposwithflags",
      "title": "`RedisModule_KeyAtPosWithFlags`",
      "role": "content",
      "text": "void RedisModule_KeyAtPosWithFlags(RedisModuleCtx *ctx, int pos, int flags);\n\n**Available since:** 7.0.0\n\nWhen a module command is called in order to obtain the position of\nkeys, since it was flagged as \"getkeys-api\" during the registration,\nthe command implementation checks for this special call using the\n[`RedisModule_IsKeysPositionRequest()`](#RedisModule_IsKeysPositionRequest) API and uses this function in\norder to report keys.\n\nThe supported flags are the ones used by [`RedisModule_SetCommandInfo`](#RedisModule_SetCommandInfo), see `REDISMODULE_CMD_KEY_`*.\n\n\nThe following is an example of how it could be used:\n\n    if (RedisModule_IsKeysPositionRequest(ctx)) {\n        RedisModule_KeyAtPosWithFlags(ctx, 2, REDISMODULE_CMD_KEY_RO | REDISMODULE_CMD_KEY_ACCESS);\n        RedisModule_KeyAtPosWithFlags(ctx, 1, REDISMODULE_CMD_KEY_RW | REDISMODULE_CMD_KEY_UPDATE | REDISMODULE_CMD_KEY_ACCESS);\n    }\n\n Note: in the example above the get keys API could have been handled by key-specs (preferred).\n Implementing the getkeys-api is required only when is it not possible to declare key-specs that cover all keys.\n\n<span id=\"RedisModule_KeyAtPos\"></span>"
    },
    {
      "id": "redismodule-keyatpos",
      "title": "`RedisModule_KeyAtPos`",
      "role": "content",
      "text": "void RedisModule_KeyAtPos(RedisModuleCtx *ctx, int pos);\n\n**Available since:** 4.0.0\n\nThis API existed before [`RedisModule_KeyAtPosWithFlags`](#RedisModule_KeyAtPosWithFlags) was added, now deprecated and\ncan be used for compatibility with older versions, before key-specs and flags\nwere introduced.\n\n<span id=\"RedisModule_IsChannelsPositionRequest\"></span>"
    },
    {
      "id": "redismodule-ischannelspositionrequest",
      "title": "`RedisModule_IsChannelsPositionRequest`",
      "role": "content",
      "text": "int RedisModule_IsChannelsPositionRequest(RedisModuleCtx *ctx);\n\n**Available since:** 7.0.0\n\nReturn non-zero if a module command, that was declared with the\nflag \"getchannels-api\", is called in a special way to get the channel positions\nand not to get executed. Otherwise zero is returned.\n\n<span id=\"RedisModule_ChannelAtPosWithFlags\"></span>"
    },
    {
      "id": "redismodule-channelatposwithflags",
      "title": "`RedisModule_ChannelAtPosWithFlags`",
      "role": "content",
      "text": "void RedisModule_ChannelAtPosWithFlags(RedisModuleCtx *ctx,\n                                           int pos,\n                                           int flags);\n\n**Available since:** 7.0.0\n\nWhen a module command is called in order to obtain the position of\nchannels, since it was flagged as \"getchannels-api\" during the\nregistration, the command implementation checks for this special call\nusing the [`RedisModule_IsChannelsPositionRequest()`](#RedisModule_IsChannelsPositionRequest) API and uses this\nfunction in order to report the channels.\n\nThe supported flags are:\n* `REDISMODULE_CMD_CHANNEL_SUBSCRIBE`: This command will subscribe to the channel.\n* `REDISMODULE_CMD_CHANNEL_UNSUBSCRIBE`: This command will unsubscribe from this channel.\n* `REDISMODULE_CMD_CHANNEL_PUBLISH`: This command will publish to this channel.\n* `REDISMODULE_CMD_CHANNEL_PATTERN`: Instead of acting on a specific channel, will act on any \n                                   channel specified by the pattern. This is the same access\n                                   used by the PSUBSCRIBE and PUNSUBSCRIBE commands available \n                                   in Redis. Not intended to be used with PUBLISH permissions.\n\nThe following is an example of how it could be used:\n\n    if (RedisModule_IsChannelsPositionRequest(ctx)) {\n        RedisModule_ChannelAtPosWithFlags(ctx, 1, REDISMODULE_CMD_CHANNEL_SUBSCRIBE | REDISMODULE_CMD_CHANNEL_PATTERN);\n        RedisModule_ChannelAtPosWithFlags(ctx, 1, REDISMODULE_CMD_CHANNEL_PUBLISH);\n    }\n\nNote: One usage of declaring channels is for evaluating ACL permissions. In this context,\nunsubscribing is always allowed, so commands will only be checked against subscribe and\npublish permissions. This is preferred over using [`RedisModule_ACLCheckChannelPermissions`](#RedisModule_ACLCheckChannelPermissions), since\nit allows the ACLs to be checked before the command is executed.\n\n<span id=\"RedisModule_CreateCommand\"></span>"
    },
    {
      "id": "redismodule-createcommand",
      "title": "`RedisModule_CreateCommand`",
      "role": "content",
      "text": "int RedisModule_CreateCommand(RedisModuleCtx *ctx,\n                                  const char *name,\n                                  RedisModuleCmdFunc cmdfunc,\n                                  const char *strflags,\n                                  int firstkey,\n                                  int lastkey,\n                                  int keystep);\n\n**Available since:** 4.0.0\n\nRegister a new command in the Redis server, that will be handled by\ncalling the function pointer 'cmdfunc' using the RedisModule calling\nconvention.\n\nThe function returns `REDISMODULE_ERR` in these cases:\n- If creation of module command is called outside the `RedisModule_OnLoad`.\n- The specified command is already busy.\n- The command name contains some chars that are not allowed.\n- A set of invalid flags were passed.\n\nOtherwise `REDISMODULE_OK` is returned and the new command is registered.\n\nThis function must be called during the initialization of the module\ninside the `RedisModule_OnLoad()` function. Calling this function outside\nof the initialization function is not defined.\n\nThe command function type is the following:\n\n     int MyCommand_RedisCommand(RedisModuleCtx *ctx, RedisModuleString **argv, int argc);\n\nAnd is supposed to always return `REDISMODULE_OK`.\n\nThe set of flags 'strflags' specify the behavior of the command, and should\nbe passed as a C string composed of space separated words, like for\nexample \"write deny-oom\". The set of flags are:\n\n* **\"write\"**:     The command may modify the data set (it may also read\n                   from it).\n* **\"readonly\"**:  The command returns data from keys but never writes.\n* **\"admin\"**:     The command is an administrative command (may change\n                   replication or perform similar tasks).\n* **\"deny-oom\"**:  The command may use additional memory and should be\n                   denied during out of memory conditions.\n* **\"deny-script\"**:   Don't allow this command in Lua scripts.\n* **\"allow-loading\"**: Allow this command while the server is loading data.\n                       Only commands not interacting with the data set\n                       should be allowed to run in this mode. If not sure\n                       don't use this flag.\n* **\"pubsub\"**:    The command publishes things on Pub/Sub channels.\n* **\"random\"**:    The command may have different outputs even starting\n                   from the same input arguments and key values.\n                   Starting from Redis 7.0 this flag has been deprecated.\n                   Declaring a command as \"random\" can be done using\n                   command tips, see https://un5pn9hmggug.julianrbryant.com/docs/latest/develop/reference/command-tips/.\n* **\"allow-stale\"**: The command is allowed to run on slaves that don't\n                     serve stale data. Don't use if you don't know what\n                     this means.\n* **\"no-monitor\"**: Don't propagate the command on monitor. Use this if\n                    the command has sensitive data among the arguments.\n* **\"no-slowlog\"**: Don't log this command in the slowlog. Use this if\n                    the command has sensitive data among the arguments.\n* **\"fast\"**:      The command time complexity is not greater\n                   than O(log(N)) where N is the size of the collection or\n                   anything else representing the normal scalability\n                   issue with the command.\n* **\"getkeys-api\"**: The command implements the interface to return\n                     the arguments that are keys. Used when start/stop/step\n                     is not enough because of the command syntax.\n* **\"no-cluster\"**: The command should not register in Redis Cluster\n                    since is not designed to work with it because, for\n                    example, is unable to report the position of the\n                    keys, programmatically creates key names, or any\n                    other reason.\n* **\"no-auth\"**:    This command can be run by an un-authenticated client.\n                    Normally this is used by a command that is used\n                    to authenticate a client.\n* **\"may-replicate\"**: This command may generate replication traffic, even\n                       though it's not a write command.\n* **\"no-mandatory-keys\"**: All the keys this command may take are optional\n* **\"blocking\"**: The command has the potential to block the client.\n* **\"allow-busy\"**: Permit the command while the server is blocked either by\n                    a script or by a slow module command, see\n                    RedisModule_Yield.\n* **\"getchannels-api\"**: The command implements the interface to return\n                         the arguments that are channels.\n* **\"internal\"**: Internal command, one that should not be exposed to the user connections.\n                  For example, module commands that are called by the modules,\n                  commands that do not perform ACL validations (relying on earlier checks)\n* **\"touches-arbitrary-keys\"**: This command may modify arbitrary keys (i.e. not provided via argv).\n                  This flag is used so we don't wrap the replicated commands with MULTI/EXEC.\n\nThe last three parameters specify which arguments of the new command are\nRedis keys. See [https://un5pn9hmggug.julianrbryant.com/commands/command](https://un5pn9hmggug.julianrbryant.com/commands/command) for more information.\n\n* `firstkey`: One-based index of the first argument that's a key.\n              Position 0 is always the command name itself.\n              0 for commands with no keys.\n* `lastkey`:  One-based index of the last argument that's a key.\n              Negative numbers refer to counting backwards from the last\n              argument (-1 means the last argument provided)\n              0 for commands with no keys.\n* `keystep`:  Step between first and last key indexes.\n              0 for commands with no keys.\n\nThis information is used by ACL, Cluster and the `COMMAND` command.\n\nNOTE: The scheme described above serves a limited purpose and can\nonly be used to find keys that exist at constant indices.\nFor non-trivial key arguments, you may pass 0,0,0 and use\n[`RedisModule_SetCommandInfo`](#RedisModule_SetCommandInfo) to set key specs using a more advanced scheme and use\n[`RedisModule_SetCommandACLCategories`](#RedisModule_SetCommandACLCategories) to set Redis ACL categories of the commands.\n\n<span id=\"RedisModule_GetCommand\"></span>"
    },
    {
      "id": "redismodule-getcommand",
      "title": "`RedisModule_GetCommand`",
      "role": "content",
      "text": "RedisModuleCommand *RedisModule_GetCommand(RedisModuleCtx *ctx,\n                                               const char *name);\n\n**Available since:** 7.0.0\n\nGet an opaque structure, representing a module command, by command name.\nThis structure is used in some of the command-related APIs.\n\nNULL is returned in case of the following errors:\n\n* Command not found\n* The command is not a module command\n* The command doesn't belong to the calling module\n\n<span id=\"RedisModule_CreateSubcommand\"></span>"
    },
    {
      "id": "redismodule-createsubcommand",
      "title": "`RedisModule_CreateSubcommand`",
      "role": "content",
      "text": "int RedisModule_CreateSubcommand(RedisModuleCommand *parent,\n                                     const char *name,\n                                     RedisModuleCmdFunc cmdfunc,\n                                     const char *strflags,\n                                     int firstkey,\n                                     int lastkey,\n                                     int keystep);\n\n**Available since:** 7.0.0\n\nVery similar to [`RedisModule_CreateCommand`](#RedisModule_CreateCommand) except that it is used to create\na subcommand, associated with another, container, command.\n\nExample: If a module has a configuration command, MODULE.CONFIG, then\nGET and SET should be individual subcommands, while MODULE.CONFIG is\na command, but should not be registered with a valid `funcptr`:\n\n     if (RedisModule_CreateCommand(ctx,\"module.config\",NULL,\"\",0,0,0) == REDISMODULE_ERR)\n         return REDISMODULE_ERR;\n\n     RedisModuleCommand *parent = RedisModule_GetCommand(ctx,,\"module.config\");\n\n     if (RedisModule_CreateSubcommand(parent,\"set\",cmd_config_set,\"\",0,0,0) == REDISMODULE_ERR)\n        return REDISMODULE_ERR;\n\n     if (RedisModule_CreateSubcommand(parent,\"get\",cmd_config_get,\"\",0,0,0) == REDISMODULE_ERR)\n        return REDISMODULE_ERR;\n\nReturns `REDISMODULE_OK` on success and `REDISMODULE_ERR` in case of the following errors:\n\n* Error while parsing `strflags`\n* Command is marked as `no-cluster` but cluster mode is enabled\n* `parent` is already a subcommand (we do not allow more than one level of command nesting)\n* `parent` is a command with an implementation (`RedisModuleCmdFunc`) (A parent command should be a pure container of subcommands)\n* `parent` already has a subcommand called `name`\n* Creating a subcommand is called outside of `RedisModule_OnLoad`.\n\n<span id=\"RedisModule_AddACLCategory\"></span>"
    },
    {
      "id": "redismodule-addaclcategory",
      "title": "`RedisModule_AddACLCategory`",
      "role": "content",
      "text": "int RedisModule_AddACLCategory(RedisModuleCtx *ctx, const char *name);\n\n**Available since:** 7.4.0\n\n[`RedisModule_AddACLCategory`](#RedisModule_AddACLCategory) can be used to add new ACL command categories. Category names\ncan only contain alphanumeric characters, underscores, or dashes. Categories can only be added\nduring the `RedisModule_OnLoad` function. Once a category has been added, it can not be removed. \nAny module can register a command to any added categories using [`RedisModule_SetCommandACLCategories`](#RedisModule_SetCommandACLCategories).\n\nReturns:\n- `REDISMODULE_OK` on successfully adding the new ACL category. \n- `REDISMODULE_ERR` on failure.\n\nOn error the errno is set to:\n- EINVAL if the name contains invalid characters.\n- EBUSY if the category name already exists.\n- ENOMEM if the number of categories reached the max limit of 64 categories.\n\n<span id=\"RedisModule_SetCommandACLCategories\"></span>"
    },
    {
      "id": "redismodule-setcommandaclcategories",
      "title": "`RedisModule_SetCommandACLCategories`",
      "role": "content",
      "text": "int RedisModule_SetCommandACLCategories(RedisModuleCommand *command,\n                                            const char *aclflags);\n\n**Available since:** 7.2.0\n\n[`RedisModule_SetCommandACLCategories`](#RedisModule_SetCommandACLCategories) can be used to set ACL categories to module\ncommands and subcommands. The set of ACL categories should be passed as\na space separated C string 'aclflags'.\n\nExample, the acl flags 'write slow' marks the command as part of the write and \nslow ACL categories.\n\nOn success `REDISMODULE_OK` is returned. On error `REDISMODULE_ERR` is returned.\n\nThis function can only be called during the `RedisModule_OnLoad` function. If called\noutside of this function, an error is returned.\n\n<span id=\"RedisModule_SetCommandInfo\"></span>"
    },
    {
      "id": "redismodule-setcommandinfo",
      "title": "`RedisModule_SetCommandInfo`",
      "role": "content",
      "text": "int RedisModule_SetCommandInfo(RedisModuleCommand *command,\n                                   const RedisModuleCommandInfo *info);\n\n**Available since:** 7.0.0\n\nSet additional command information.\n\nAffects the output of `COMMAND`, `COMMAND INFO` and `COMMAND DOCS`, Cluster,\nACL and is used to filter commands with the wrong number of arguments before\nthe call reaches the module code.\n\nThis function can be called after creating a command using [`RedisModule_CreateCommand`](#RedisModule_CreateCommand)\nand fetching the command pointer using [`RedisModule_GetCommand`](#RedisModule_GetCommand). The information can\nonly be set once for each command and has the following structure:\n\n    typedef struct RedisModuleCommandInfo {\n        const RedisModuleCommandInfoVersion *version;\n        const char *summary;\n        const char *complexity;\n        const char *since;\n        RedisModuleCommandHistoryEntry *history;\n        const char *tips;\n        int arity;\n        RedisModuleCommandKeySpec *key_specs;\n        RedisModuleCommandArg *args;\n    } RedisModuleCommandInfo;\n\nAll fields except `version` are optional. Explanation of the fields:\n\n- `version`: This field enables compatibility with different Redis versions.\n  Always set this field to `REDISMODULE_COMMAND_INFO_VERSION`.\n\n- `summary`: A short description of the command (optional).\n\n- `complexity`: Complexity description (optional).\n\n- `since`: The version where the command was introduced (optional).\n  Note: The version specified should be the module's, not Redis version.\n\n- `history`: An array of `RedisModuleCommandHistoryEntry` (optional), which is\n  a struct with the following fields:\n\n        const char *since;\n        const char *changes;\n\n    `since` is a version string and `changes` is a string describing the\n    changes. The array is terminated by a zeroed entry, i.e. an entry with\n    both strings set to NULL.\n\n- `tips`: A string of space-separated tips regarding this command, meant for\n  clients and proxies. See [https://un5pn9hmggug.julianrbryant.com/docs/latest/develop/reference/command-tips/](https://un5pn9hmggug.julianrbryant.com/docs/latest/develop/reference/command-tips/).\n\n- `arity`: Number of arguments, including the command name itself. A positive\n  number specifies an exact number of arguments and a negative number\n  specifies a minimum number of arguments, so use -N to say >= N. Redis\n  validates a call before passing it to a module, so this can replace an\n  arity check inside the module command implementation. A value of 0 (or an\n  omitted arity field) is equivalent to -2 if the command has sub commands\n  and -1 otherwise.\n\n- `key_specs`: An array of `RedisModuleCommandKeySpec`, terminated by an\n  element memset to zero. This is a scheme that tries to describe the\n  positions of key arguments better than the old [`RedisModule_CreateCommand`](#RedisModule_CreateCommand) arguments\n  `firstkey`, `lastkey`, `keystep` and is needed if those three are not\n  enough to describe the key positions. There are two steps to retrieve key\n  positions: *begin search* (BS) in which index should find the first key and\n  *find keys* (FK) which, relative to the output of BS, describes how can we\n  will which arguments are keys. Additionally, there are key specific flags.\n\n    Key-specs cause the triplet (firstkey, lastkey, keystep) given in\n    RedisModule_CreateCommand to be recomputed, but it is still useful to provide\n    these three parameters in RedisModule_CreateCommand, to better support old Redis\n    versions where RedisModule_SetCommandInfo is not available.\n\n    Note that key-specs don't fully replace the \"getkeys-api\" (see\n    RedisModule_CreateCommand, RedisModule_IsKeysPositionRequest and RedisModule_KeyAtPosWithFlags) so\n    it may be a good idea to supply both key-specs and implement the\n    getkeys-api.\n\n    A key-spec has the following structure:\n\n        typedef struct RedisModuleCommandKeySpec {\n            const char *notes;\n            uint64_t flags;\n            RedisModuleKeySpecBeginSearchType begin_search_type;\n            union {\n                struct {\n                    int pos;\n                } index;\n                struct {\n                    const char *keyword;\n                    int startfrom;\n                } keyword;\n            } bs;\n            RedisModuleKeySpecFindKeysType find_keys_type;\n            union {\n                struct {\n                    int lastkey;\n                    int keystep;\n                    int limit;\n                } range;\n                struct {\n                    int keynumidx;\n                    int firstkey;\n                    int keystep;\n                } keynum;\n            } fk;\n        } RedisModuleCommandKeySpec;\n\n    Explanation of the fields of RedisModuleCommandKeySpec:\n\n    * `notes`: Optional notes or clarifications about this key spec.\n\n    * `flags`: A bitwise or of key-spec flags described below.\n\n    * `begin_search_type`: This describes how the first key is discovered.\n      There are two ways to determine the first key:\n\n        * `REDISMODULE_KSPEC_BS_UNKNOWN`: There is no way to tell where the\n          key args start.\n        * `REDISMODULE_KSPEC_BS_INDEX`: Key args start at a constant index.\n        * `REDISMODULE_KSPEC_BS_KEYWORD`: Key args start just after a\n          specific keyword.\n\n    * `bs`: This is a union in which the `index` or `keyword` branch is used\n      depending on the value of the `begin_search_type` field.\n\n        * `bs.index.pos`: The index from which we start the search for keys.\n          (`REDISMODULE_KSPEC_BS_INDEX` only.)\n\n        * `bs.keyword.keyword`: The keyword (string) that indicates the\n          beginning of key arguments. (`REDISMODULE_KSPEC_BS_KEYWORD` only.)\n\n        * `bs.keyword.startfrom`: An index in argv from which to start\n          searching. Can be negative, which means start search from the end,\n          in reverse. Example: -2 means to start in reverse from the\n          penultimate argument. (`REDISMODULE_KSPEC_BS_KEYWORD` only.)\n\n    * `find_keys_type`: After the \"begin search\", this describes which\n      arguments are keys. The strategies are:\n\n        * `REDISMODULE_KSPEC_BS_UNKNOWN`: There is no way to tell where the\n          key args are located.\n        * `REDISMODULE_KSPEC_FK_RANGE`: Keys end at a specific index (or\n          relative to the last argument).\n        * `REDISMODULE_KSPEC_FK_KEYNUM`: There's an argument that contains\n          the number of key args somewhere before the keys themselves.\n\n      `find_keys_type` and `fk` can be omitted if this keyspec describes\n      exactly one key.\n\n    * `fk`: This is a union in which the `range` or `keynum` branch is used\n      depending on the value of the `find_keys_type` field.\n\n        * `fk.range` (for `REDISMODULE_KSPEC_FK_RANGE`): A struct with the\n          following fields:\n\n            * `lastkey`: Index of the last key relative to the result of the\n              begin search step. Can be negative, in which case it's not\n              relative. -1 indicates the last argument, -2 one before the\n              last and so on.\n\n            * `keystep`: How many arguments should we skip after finding a\n              key, in order to find the next one?\n\n            * `limit`: If `lastkey` is -1, we use `limit` to stop the search\n              by a factor. 0 and 1 mean no limit. 2 means 1/2 of the\n              remaining args, 3 means 1/3, and so on.\n\n        * `fk.keynum` (for `REDISMODULE_KSPEC_FK_KEYNUM`): A struct with the\n          following fields:\n\n            * `keynumidx`: Index of the argument containing the number of\n              keys to come, relative to the result of the begin search step.\n\n            * `firstkey`: Index of the fist key relative to the result of the\n              begin search step. (Usually it's just after `keynumidx`, in\n              which case it should be set to `keynumidx + 1`.)\n\n            * `keystep`: How many arguments should we skip after finding a\n              key, in order to find the next one?\n\n    Key-spec flags:\n\n    The first four refer to what the command actually does with the *value or\n    metadata of the key*, and not necessarily the user data or how it affects\n    it. Each key-spec may must have exactly one of these. Any operation\n    that's not distinctly deletion, overwrite or read-only would be marked as\n    RW.\n\n    * `REDISMODULE_CMD_KEY_RO`: Read-Only. Reads the value of the key, but\n      doesn't necessarily return it.\n\n    * `REDISMODULE_CMD_KEY_RW`: Read-Write. Modifies the data stored in the\n      value of the key or its metadata.\n\n    * `REDISMODULE_CMD_KEY_OW`: Overwrite. Overwrites the data stored in the\n      value of the key.\n\n    * `REDISMODULE_CMD_KEY_RM`: Deletes the key.\n\n    The next four refer to *user data inside the value of the key*, not the\n    metadata like LRU, type, cardinality. It refers to the logical operation\n    on the user's data (actual input strings or TTL), being\n    used/returned/copied/changed. It doesn't refer to modification or\n    returning of metadata (like type, count, presence of data). ACCESS can be\n    combined with one of the write operations INSERT, DELETE or UPDATE. Any\n    write that's not an INSERT or a DELETE would be UPDATE.\n\n    * `REDISMODULE_CMD_KEY_ACCESS`: Returns, copies or uses the user data\n      from the value of the key.\n\n    * `REDISMODULE_CMD_KEY_UPDATE`: Updates data to the value, new value may\n      depend on the old value.\n\n    * `REDISMODULE_CMD_KEY_INSERT`: Adds data to the value with no chance of\n      modification or deletion of existing data.\n\n    * `REDISMODULE_CMD_KEY_DELETE`: Explicitly deletes some content from the\n      value of the key.\n\n    Other flags:\n\n    * `REDISMODULE_CMD_KEY_NOT_KEY`: The key is not actually a key, but \n      should be routed in cluster mode as if it was a key.\n\n    * `REDISMODULE_CMD_KEY_INCOMPLETE`: The keyspec might not point out all\n      the keys it should cover.\n\n    * `REDISMODULE_CMD_KEY_VARIABLE_FLAGS`: Some keys might have different\n      flags depending on arguments.\n\n- `args`: An array of `RedisModuleCommandArg`, terminated by an element memset\n  to zero. `RedisModuleCommandArg` is a structure with at the fields described\n  below.\n\n        typedef struct RedisModuleCommandArg {\n            const char *name;\n            RedisModuleCommandArgType type;\n            int key_spec_index;\n            const char *token;\n            const char *summary;\n            const char *since;\n            int flags;\n            struct RedisModuleCommandArg *subargs;\n        } RedisModuleCommandArg;\n\n    Explanation of the fields:\n\n    * `name`: Name of the argument.\n\n    * `type`: The type of the argument. See below for details. The types\n      `REDISMODULE_ARG_TYPE_ONEOF` and `REDISMODULE_ARG_TYPE_BLOCK` require\n      an argument to have sub-arguments, i.e. `subargs`.\n\n    * `key_spec_index`: If the `type` is `REDISMODULE_ARG_TYPE_KEY` you must\n      provide the index of the key-spec associated with this argument. See\n      `key_specs` above. If the argument is not a key, you may specify -1.\n\n    * `token`: The token preceding the argument (optional). Example: the\n      argument `seconds` in `SET` has a token `EX`. If the argument consists\n      of only a token (for example `NX` in `SET`) the type should be\n      `REDISMODULE_ARG_TYPE_PURE_TOKEN` and `value` should be NULL.\n\n    * `summary`: A short description of the argument (optional).\n\n    * `since`: The first version which included this argument (optional).\n\n    * `flags`: A bitwise or of the macros `REDISMODULE_CMD_ARG_*`. See below.\n\n    * `value`: The display-value of the argument. This string is what should\n      be displayed when creating the command syntax from the output of\n      `COMMAND`. If `token` is not NULL, it should also be displayed.\n\n    Explanation of `RedisModuleCommandArgType`:\n\n    * `REDISMODULE_ARG_TYPE_STRING`: String argument.\n    * `REDISMODULE_ARG_TYPE_INTEGER`: Integer argument.\n    * `REDISMODULE_ARG_TYPE_DOUBLE`: Double-precision float argument.\n    * `REDISMODULE_ARG_TYPE_KEY`: String argument representing a keyname.\n    * `REDISMODULE_ARG_TYPE_PATTERN`: String, but regex pattern.\n    * `REDISMODULE_ARG_TYPE_UNIX_TIME`: Integer, but Unix timestamp.\n    * `REDISMODULE_ARG_TYPE_PURE_TOKEN`: Argument doesn't have a placeholder.\n      It's just a token without a value. Example: the `KEEPTTL` option of the\n      `SET` command.\n    * `REDISMODULE_ARG_TYPE_ONEOF`: Used when the user can choose only one of\n      a few sub-arguments. Requires `subargs`. Example: the `NX` and `XX`\n      options of `SET`.\n    * `REDISMODULE_ARG_TYPE_BLOCK`: Used when one wants to group together\n      several sub-arguments, usually to apply something on all of them, like\n      making the entire group \"optional\". Requires `subargs`. Example: the\n      `LIMIT offset count` parameters in `ZRANGE`.\n\n    Explanation of the command argument flags:\n\n    * `REDISMODULE_CMD_ARG_OPTIONAL`: The argument is optional (like GET in\n      the SET command).\n    * `REDISMODULE_CMD_ARG_MULTIPLE`: The argument may repeat itself (like\n      key in DEL).\n    * `REDISMODULE_CMD_ARG_MULTIPLE_TOKEN`: The argument may repeat itself,\n      and so does its token (like `GET pattern` in SORT).\n\nOn success `REDISMODULE_OK` is returned. On error `REDISMODULE_ERR` is returned\nand `errno` is set to EINVAL if invalid info was provided or EEXIST if info\nhas already been set. If the info is invalid, a warning is logged explaining\nwhich part of the info is invalid and why.\n\n<span id=\"section-module-information-and-time-measurement\"></span>"
    },
    {
      "id": "module-information-and-time-measurement",
      "title": "Module information and time measurement",
      "role": "content",
      "text": "<span id=\"RedisModule_IsModuleNameBusy\"></span>"
    },
    {
      "id": "redismodule-ismodulenamebusy",
      "title": "`RedisModule_IsModuleNameBusy`",
      "role": "content",
      "text": "int RedisModule_IsModuleNameBusy(const char *name);\n\n**Available since:** 4.0.3\n\nReturn non-zero if the module name is busy.\nOtherwise zero is returned.\n\n<span id=\"RedisModule_Milliseconds\"></span>"
    },
    {
      "id": "redismodule-milliseconds",
      "title": "`RedisModule_Milliseconds`",
      "role": "content",
      "text": "mstime_t RedisModule_Milliseconds(void);\n\n**Available since:** 4.0.0\n\nReturn the current UNIX time in milliseconds.\n\n<span id=\"RedisModule_MonotonicMicroseconds\"></span>"
    },
    {
      "id": "redismodule-monotonicmicroseconds",
      "title": "`RedisModule_MonotonicMicroseconds`",
      "role": "content",
      "text": "uint64_t RedisModule_MonotonicMicroseconds(void);\n\n**Available since:** 7.0.0\n\nReturn counter of micro-seconds relative to an arbitrary point in time.\n\n<span id=\"RedisModule_Microseconds\"></span>"
    },
    {
      "id": "redismodule-microseconds",
      "title": "`RedisModule_Microseconds`",
      "role": "content",
      "text": "ustime_t RedisModule_Microseconds(void);\n\n**Available since:** 7.2.0\n\nReturn the current UNIX time in microseconds\n\n<span id=\"RedisModule_CachedMicroseconds\"></span>"
    },
    {
      "id": "redismodule-cachedmicroseconds",
      "title": "`RedisModule_CachedMicroseconds`",
      "role": "content",
      "text": "ustime_t RedisModule_CachedMicroseconds(void);\n\n**Available since:** 7.2.0\n\nReturn the cached UNIX time in microseconds.\nIt is updated in the server cron job and before executing a command.\nIt is useful for complex call stacks, such as a command causing a\nkey space notification, causing a module to execute a [`RedisModule_Call`](#RedisModule_Call),\ncausing another notification, etc.\nIt makes sense that all this callbacks would use the same clock.\n\n<span id=\"RedisModule_BlockedClientMeasureTimeStart\"></span>"
    },
    {
      "id": "redismodule-blockedclientmeasuretimestart",
      "title": "`RedisModule_BlockedClientMeasureTimeStart`",
      "role": "content",
      "text": "int RedisModule_BlockedClientMeasureTimeStart(RedisModuleBlockedClient *bc);\n\n**Available since:** 6.2.0\n\nMark a point in time that will be used as the start time to calculate\nthe elapsed execution time when [`RedisModule_BlockedClientMeasureTimeEnd()`](#RedisModule_BlockedClientMeasureTimeEnd) is called.\nWithin the same command, you can call multiple times\n[`RedisModule_BlockedClientMeasureTimeStart()`](#RedisModule_BlockedClientMeasureTimeStart) and [`RedisModule_BlockedClientMeasureTimeEnd()`](#RedisModule_BlockedClientMeasureTimeEnd)\nto accumulate independent time intervals to the background duration.\nThis method always return `REDISMODULE_OK`.\n\nThis function is not thread safe, If used in module thread and blocked callback (possibly main thread)\nsimultaneously, it's recommended to protect them with lock owned by caller instead of GIL.\n\n<span id=\"RedisModule_BlockedClientMeasureTimeEnd\"></span>"
    },
    {
      "id": "redismodule-blockedclientmeasuretimeend",
      "title": "`RedisModule_BlockedClientMeasureTimeEnd`",
      "role": "content",
      "text": "int RedisModule_BlockedClientMeasureTimeEnd(RedisModuleBlockedClient *bc);\n\n**Available since:** 6.2.0\n\nMark a point in time that will be used as the end time\nto calculate the elapsed execution time.\nOn success `REDISMODULE_OK` is returned.\nThis method only returns `REDISMODULE_ERR` if no start time was\npreviously defined ( meaning [`RedisModule_BlockedClientMeasureTimeStart`](#RedisModule_BlockedClientMeasureTimeStart) was not called ).\n\nThis function is not thread safe, If used in module thread and blocked callback (possibly main thread)\nsimultaneously, it's recommended to protect them with lock owned by caller instead of GIL.\n\n<span id=\"RedisModule_Yield\"></span>"
    },
    {
      "id": "redismodule-yield",
      "title": "`RedisModule_Yield`",
      "role": "content",
      "text": "void RedisModule_Yield(RedisModuleCtx *ctx, int flags, const char *busy_reply);\n\n**Available since:** 7.0.0\n\nThis API allows modules to let Redis process background tasks, and some\ncommands during long blocking execution of a module command.\nThe module can call this API periodically.\nThe flags is a bit mask of these:\n\n- `REDISMODULE_YIELD_FLAG_NONE`: No special flags, can perform some background\n                                 operations, but not process client commands.\n- `REDISMODULE_YIELD_FLAG_CLIENTS`: Redis can also process client commands.\n\nThe `busy_reply` argument is optional, and can be used to control the verbose\nerror string after the `-BUSY` error code.\n\nWhen the `REDISMODULE_YIELD_FLAG_CLIENTS` is used, Redis will only start\nprocessing client commands after the time defined by the\n`busy-reply-threshold` config, in which case Redis will start rejecting most\ncommands with `-BUSY` error, but allow the ones marked with the `allow-busy`\nflag to be executed.\nThis API can also be used in thread safe context (while locked), and during\nloading (in the `rdb_load` callback, in which case it'll reject commands with\nthe -LOADING error)\n\n<span id=\"RedisModule_SetModuleOptions\"></span>"
    },
    {
      "id": "redismodule-setmoduleoptions",
      "title": "`RedisModule_SetModuleOptions`",
      "role": "content",
      "text": "void RedisModule_SetModuleOptions(RedisModuleCtx *ctx, int options);\n\n**Available since:** 6.0.0\n\nSet flags defining capabilities or behavior bit flags.\n\n`REDISMODULE_OPTIONS_HANDLE_IO_ERRORS`:\nGenerally, modules don't need to bother with this, as the process will just\nterminate if a read error happens, however, setting this flag would allow\nrepl-diskless-load to work if enabled.\nThe module should use [`RedisModule_IsIOError`](#RedisModule_IsIOError) after reads, before using the\ndata that was read, and in case of error, propagate it upwards, and also be\nable to release the partially populated value and all it's allocations.\n\n`REDISMODULE_OPTION_NO_IMPLICIT_SIGNAL_MODIFIED`:\nSee [`RedisModule_SignalModifiedKey()`](#RedisModule_SignalModifiedKey).\n\n`REDISMODULE_OPTIONS_HANDLE_REPL_ASYNC_LOAD`:\nSetting this flag indicates module awareness of diskless async replication (repl-diskless-load=swapdb)\nand that redis could be serving reads during replication instead of blocking with LOADING status.\n\n`REDISMODULE_OPTIONS_ALLOW_NESTED_KEYSPACE_NOTIFICATIONS`:\nDeclare that the module wants to get nested key-space notifications.\nBy default, Redis will not fire key-space notifications that happened inside\na key-space notification callback. This flag allows to change this behavior\nand fire nested key-space notifications. Notice: if enabled, the module\nshould protected itself from infinite recursion.\n\n<span id=\"RedisModule_SignalModifiedKey\"></span>"
    },
    {
      "id": "redismodule-signalmodifiedkey",
      "title": "`RedisModule_SignalModifiedKey`",
      "role": "content",
      "text": "int RedisModule_SignalModifiedKey(RedisModuleCtx *ctx,\n                                      RedisModuleString *keyname);\n\n**Available since:** 6.0.0\n\nSignals that the key is modified from user's perspective (i.e. invalidate WATCH\nand client side caching).\n\nThis is done automatically when a key opened for writing is closed, unless\nthe option `REDISMODULE_OPTION_NO_IMPLICIT_SIGNAL_MODIFIED` has been set using\n[`RedisModule_SetModuleOptions()`](#RedisModule_SetModuleOptions).\n\n<span id=\"section-automatic-memory-management-for-modules\"></span>"
    },
    {
      "id": "automatic-memory-management-for-modules",
      "title": "Automatic memory management for modules",
      "role": "content",
      "text": "<span id=\"RedisModule_AutoMemory\"></span>"
    },
    {
      "id": "redismodule-automemory",
      "title": "`RedisModule_AutoMemory`",
      "role": "content",
      "text": "void RedisModule_AutoMemory(RedisModuleCtx *ctx);\n\n**Available since:** 4.0.0\n\nEnable automatic memory management.\n\nThe function must be called as the first function of a command implementation\nthat wants to use automatic memory.\n\nWhen enabled, automatic memory management tracks and automatically frees\nkeys, call replies and Redis string objects once the command returns. In most\ncases this eliminates the need of calling the following functions:\n\n1. [`RedisModule_CloseKey()`](#RedisModule_CloseKey)\n2. [`RedisModule_FreeCallReply()`](#RedisModule_FreeCallReply)\n3. [`RedisModule_FreeString()`](#RedisModule_FreeString)\n\nThese functions can still be used with automatic memory management enabled,\nto optimize loops that make numerous allocations for example.\n\n<span id=\"section-string-objects-apis\"></span>"
    },
    {
      "id": "string-objects-apis",
      "title": "String objects APIs",
      "role": "content",
      "text": "<span id=\"RedisModule_CreateString\"></span>"
    },
    {
      "id": "redismodule-createstring",
      "title": "`RedisModule_CreateString`",
      "role": "content",
      "text": "RedisModuleString *RedisModule_CreateString(RedisModuleCtx *ctx,\n                                                const char *ptr,\n                                                size_t len);\n\n**Available since:** 4.0.0\n\nCreate a new module string object. The returned string must be freed\nwith [`RedisModule_FreeString()`](#RedisModule_FreeString), unless automatic memory is enabled.\n\nThe string is created by copying the `len` bytes starting\nat `ptr`. No reference is retained to the passed buffer.\n\nThe module context 'ctx' is optional and may be NULL if you want to create\na string out of the context scope. However in that case, the automatic\nmemory management will not be available, and the string memory must be\nmanaged manually.\n\n<span id=\"RedisModule_CreateStringPrintf\"></span>"
    },
    {
      "id": "redismodule-createstringprintf",
      "title": "`RedisModule_CreateStringPrintf`",
      "role": "content",
      "text": "RedisModuleString *RedisModule_CreateStringPrintf(RedisModuleCtx *ctx,\n                                                      const char *fmt,\n                                                      ...);\n\n**Available since:** 4.0.0\n\nCreate a new module string object from a printf format and arguments.\nThe returned string must be freed with [`RedisModule_FreeString()`](#RedisModule_FreeString), unless\nautomatic memory is enabled.\n\nThe string is created using the sds formatter function `sdscatvprintf()`.\n\nThe passed context 'ctx' may be NULL if necessary, see the\n[`RedisModule_CreateString()`](#RedisModule_CreateString) documentation for more info.\n\n<span id=\"RedisModule_CreateStringFromLongLong\"></span>"
    },
    {
      "id": "redismodule-createstringfromlonglong",
      "title": "`RedisModule_CreateStringFromLongLong`",
      "role": "content",
      "text": "RedisModuleString *RedisModule_CreateStringFromLongLong(RedisModuleCtx *ctx,\n                                                            long long ll);\n\n**Available since:** 4.0.0\n\nLike [`RedisModule_CreateString()`](#RedisModule_CreateString), but creates a string starting from a `long long`\ninteger instead of taking a buffer and its length.\n\nThe returned string must be released with [`RedisModule_FreeString()`](#RedisModule_FreeString) or by\nenabling automatic memory management.\n\nThe passed context 'ctx' may be NULL if necessary, see the\n[`RedisModule_CreateString()`](#RedisModule_CreateString) documentation for more info.\n\n<span id=\"RedisModule_CreateStringFromULongLong\"></span>"
    },
    {
      "id": "redismodule-createstringfromulonglong",
      "title": "`RedisModule_CreateStringFromULongLong`",
      "role": "content",
      "text": "RedisModuleString *RedisModule_CreateStringFromULongLong(RedisModuleCtx *ctx,\n                                                             unsigned long long ull);\n\n**Available since:** 7.0.3\n\nLike [`RedisModule_CreateString()`](#RedisModule_CreateString), but creates a string starting from a `unsigned long long`\ninteger instead of taking a buffer and its length.\n\nThe returned string must be released with [`RedisModule_FreeString()`](#RedisModule_FreeString) or by\nenabling automatic memory management.\n\nThe passed context 'ctx' may be NULL if necessary, see the\n[`RedisModule_CreateString()`](#RedisModule_CreateString) documentation for more info.\n\n<span id=\"RedisModule_CreateStringFromDouble\"></span>"
    },
    {
      "id": "redismodule-createstringfromdouble",
      "title": "`RedisModule_CreateStringFromDouble`",
      "role": "content",
      "text": "RedisModuleString *RedisModule_CreateStringFromDouble(RedisModuleCtx *ctx,\n                                                          double d);\n\n**Available since:** 6.0.0\n\nLike [`RedisModule_CreateString()`](#RedisModule_CreateString), but creates a string starting from a double\ninstead of taking a buffer and its length.\n\nThe returned string must be released with [`RedisModule_FreeString()`](#RedisModule_FreeString) or by\nenabling automatic memory management.\n\n<span id=\"RedisModule_CreateStringFromLongDouble\"></span>"
    },
    {
      "id": "redismodule-createstringfromlongdouble",
      "title": "`RedisModule_CreateStringFromLongDouble`",
      "role": "content",
      "text": "RedisModuleString *RedisModule_CreateStringFromLongDouble(RedisModuleCtx *ctx,\n                                                              long double ld,\n                                                              int humanfriendly);\n\n**Available since:** 6.0.0\n\nLike [`RedisModule_CreateString()`](#RedisModule_CreateString), but creates a string starting from a long\ndouble.\n\nThe returned string must be released with [`RedisModule_FreeString()`](#RedisModule_FreeString) or by\nenabling automatic memory management.\n\nThe passed context 'ctx' may be NULL if necessary, see the\n[`RedisModule_CreateString()`](#RedisModule_CreateString) documentation for more info.\n\n<span id=\"RedisModule_CreateStringFromString\"></span>"
    },
    {
      "id": "redismodule-createstringfromstring",
      "title": "`RedisModule_CreateStringFromString`",
      "role": "content",
      "text": "RedisModuleString *RedisModule_CreateStringFromString(RedisModuleCtx *ctx,\n                                                          const RedisModuleString *str);\n\n**Available since:** 4.0.0\n\nLike [`RedisModule_CreateString()`](#RedisModule_CreateString), but creates a string starting from another\n`RedisModuleString`.\n\nThe returned string must be released with [`RedisModule_FreeString()`](#RedisModule_FreeString) or by\nenabling automatic memory management.\n\nThe passed context 'ctx' may be NULL if necessary, see the\n[`RedisModule_CreateString()`](#RedisModule_CreateString) documentation for more info.\n\n<span id=\"RedisModule_CreateStringFromStreamID\"></span>"
    },
    {
      "id": "redismodule-createstringfromstreamid",
      "title": "`RedisModule_CreateStringFromStreamID`",
      "role": "content",
      "text": "RedisModuleString *RedisModule_CreateStringFromStreamID(RedisModuleCtx *ctx,\n                                                            const RedisModuleStreamID *id);\n\n**Available since:** 6.2.0\n\nCreates a string from a stream ID. The returned string must be released with\n[`RedisModule_FreeString()`](#RedisModule_FreeString), unless automatic memory is enabled.\n\nThe passed context `ctx` may be NULL if necessary. See the\n[`RedisModule_CreateString()`](#RedisModule_CreateString) documentation for more info.\n\n<span id=\"RedisModule_FreeString\"></span>"
    },
    {
      "id": "redismodule-freestring",
      "title": "`RedisModule_FreeString`",
      "role": "content",
      "text": "void RedisModule_FreeString(RedisModuleCtx *ctx, RedisModuleString *str);\n\n**Available since:** 4.0.0\n\nFree a module string object obtained with one of the Redis modules API calls\nthat return new string objects.\n\nIt is possible to call this function even when automatic memory management\nis enabled. In that case the string will be released ASAP and removed\nfrom the pool of string to release at the end.\n\nIf the string was created with a NULL context 'ctx', it is also possible to\npass ctx as NULL when releasing the string (but passing a context will not\ncreate any issue). Strings created with a context should be freed also passing\nthe context, so if you want to free a string out of context later, make sure\nto create it using a NULL context.\n\nThis API is not thread safe, access to these retained strings (if they originated\nfrom a client command arguments) must be done with GIL locked.\n\n<span id=\"RedisModule_RetainString\"></span>"
    },
    {
      "id": "redismodule-retainstring",
      "title": "`RedisModule_RetainString`",
      "role": "content",
      "text": "void RedisModule_RetainString(RedisModuleCtx *ctx, RedisModuleString *str);\n\n**Available since:** 4.0.0\n\nEvery call to this function, will make the string 'str' requiring\nan additional call to [`RedisModule_FreeString()`](#RedisModule_FreeString) in order to really\nfree the string. Note that the automatic freeing of the string obtained\nenabling modules automatic memory management counts for one\n[`RedisModule_FreeString()`](#RedisModule_FreeString) call (it is just executed automatically).\n\nNormally you want to call this function when, at the same time\nthe following conditions are true:\n\n1. You have automatic memory management enabled.\n2. You want to create string objects.\n3. Those string objects you create need to live *after* the callback\n   function(for example a command implementation) creating them returns.\n\nUsually you want this in order to store the created string object\ninto your own data structure, for example when implementing a new data\ntype.\n\nNote that when memory management is turned off, you don't need\nany call to RetainString() since creating a string will always result\ninto a string that lives after the callback function returns, if\nno FreeString() call is performed.\n\nIt is possible to call this function with a NULL context.\n\nWhen strings are going to be retained for an extended duration, it is good\npractice to also call [`RedisModule_TrimStringAllocation()`](#RedisModule_TrimStringAllocation) in order to\noptimize memory usage.\n\nThreaded modules that reference retained strings from other threads *must*\nexplicitly trim the allocation as soon as the string is retained. Not doing\nso may result with automatic trimming which is not thread safe.\n\nThis API is not thread safe, access to these retained strings (if they originated\nfrom a client command arguments) must be done with GIL locked.\n\n<span id=\"RedisModule_HoldString\"></span>"
    },
    {
      "id": "redismodule-holdstring",
      "title": "`RedisModule_HoldString`",
      "role": "content",
      "text": "RedisModuleString* RedisModule_HoldString(RedisModuleCtx *ctx,\n                                              RedisModuleString *str);\n\n**Available since:** 6.0.7\n\n\nThis function can be used instead of [`RedisModule_RetainString()`](#RedisModule_RetainString).\nThe main difference between the two is that this function will always\nsucceed, whereas [`RedisModule_RetainString()`](#RedisModule_RetainString) may fail because of an\nassertion.\n\nThe function returns a pointer to `RedisModuleString`, which is owned\nby the caller. It requires a call to [`RedisModule_FreeString()`](#RedisModule_FreeString) to free\nthe string when automatic memory management is disabled for the context.\nWhen automatic memory management is enabled, you can either call\n[`RedisModule_FreeString()`](#RedisModule_FreeString) or let the automation free it.\n\nThis function is more efficient than [`RedisModule_CreateStringFromString()`](#RedisModule_CreateStringFromString)\nbecause whenever possible, it avoids copying the underlying\n`RedisModuleString`. The disadvantage of using this function is that it\nmight not be possible to use [`RedisModule_StringAppendBuffer()`](#RedisModule_StringAppendBuffer) on the\nreturned `RedisModuleString`.\n\nIt is possible to call this function with a NULL context.\n\nWhen strings are going to be held for an extended duration, it is good\npractice to also call [`RedisModule_TrimStringAllocation()`](#RedisModule_TrimStringAllocation) in order to\noptimize memory usage.\n\nThreaded modules that reference held strings from other threads *must*\nexplicitly trim the allocation as soon as the string is held. Not doing\nso may result with automatic trimming which is not thread safe.\n\nThis API is not thread safe, access to these retained strings (if they originated\nfrom a client command arguments) must be done with GIL locked.\n\n<span id=\"RedisModule_StringPtrLen\"></span>"
    },
    {
      "id": "redismodule-stringptrlen",
      "title": "`RedisModule_StringPtrLen`",
      "role": "content",
      "text": "const char *RedisModule_StringPtrLen(const RedisModuleString *str,\n                                         size_t *len);\n\n**Available since:** 4.0.0\n\nGiven a string module object, this function returns the string pointer\nand length of the string. The returned pointer and length should only\nbe used for read only accesses and never modified.\n\n<span id=\"RedisModule_StringToLongLong\"></span>"
    },
    {
      "id": "redismodule-stringtolonglong",
      "title": "`RedisModule_StringToLongLong`",
      "role": "content",
      "text": "int RedisModule_StringToLongLong(const RedisModuleString *str, long long *ll);\n\n**Available since:** 4.0.0\n\nConvert the string into a `long long` integer, storing it at `*ll`.\nReturns `REDISMODULE_OK` on success. If the string can't be parsed\nas a valid, strict `long long` (no spaces before/after), `REDISMODULE_ERR`\nis returned.\n\n<span id=\"RedisModule_StringToULongLong\"></span>"
    },
    {
      "id": "redismodule-stringtoulonglong",
      "title": "`RedisModule_StringToULongLong`",
      "role": "content",
      "text": "int RedisModule_StringToULongLong(const RedisModuleString *str,\n                                      unsigned long long *ull);\n\n**Available since:** 7.0.3\n\nConvert the string into a `unsigned long long` integer, storing it at `*ull`.\nReturns `REDISMODULE_OK` on success. If the string can't be parsed\nas a valid, strict `unsigned long long` (no spaces before/after), `REDISMODULE_ERR`\nis returned.\n\n<span id=\"RedisModule_StringToDouble\"></span>"
    },
    {
      "id": "redismodule-stringtodouble",
      "title": "`RedisModule_StringToDouble`",
      "role": "content",
      "text": "int RedisModule_StringToDouble(const RedisModuleString *str, double *d);\n\n**Available since:** 4.0.0\n\nConvert the string into a double, storing it at `*d`.\nReturns `REDISMODULE_OK` on success or `REDISMODULE_ERR` if the string is\nnot a valid string representation of a double value.\n\n<span id=\"RedisModule_StringToLongDouble\"></span>"
    },
    {
      "id": "redismodule-stringtolongdouble",
      "title": "`RedisModule_StringToLongDouble`",
      "role": "content",
      "text": "int RedisModule_StringToLongDouble(const RedisModuleString *str,\n                                       long double *ld);\n\n**Available since:** 6.0.0\n\nConvert the string into a long double, storing it at `*ld`.\nReturns `REDISMODULE_OK` on success or `REDISMODULE_ERR` if the string is\nnot a valid string representation of a double value.\n\n<span id=\"RedisModule_StringToStreamID\"></span>"
    },
    {
      "id": "redismodule-stringtostreamid",
      "title": "`RedisModule_StringToStreamID`",
      "role": "content",
      "text": "int RedisModule_StringToStreamID(const RedisModuleString *str,\n                                     RedisModuleStreamID *id);\n\n**Available since:** 6.2.0\n\nConvert the string into a stream ID, storing it at `*id`.\nReturns `REDISMODULE_OK` on success and returns `REDISMODULE_ERR` if the string\nis not a valid string representation of a stream ID. The special IDs \"+\" and\n\"-\" are allowed.\n\n<span id=\"RedisModule_StringCompare\"></span>"
    },
    {
      "id": "redismodule-stringcompare",
      "title": "`RedisModule_StringCompare`",
      "role": "content",
      "text": "int RedisModule_StringCompare(const RedisModuleString *a,\n                                  const RedisModuleString *b);\n\n**Available since:** 4.0.0\n\nCompare two string objects, returning -1, 0 or 1 respectively if\na < b, a == b, a > b. Strings are compared byte by byte as two\nbinary blobs without any encoding care / collation attempt.\n\n<span id=\"RedisModule_StringAppendBuffer\"></span>"
    },
    {
      "id": "redismodule-stringappendbuffer",
      "title": "`RedisModule_StringAppendBuffer`",
      "role": "content",
      "text": "int RedisModule_StringAppendBuffer(RedisModuleCtx *ctx,\n                                       RedisModuleString *str,\n                                       const char *buf,\n                                       size_t len);\n\n**Available since:** 4.0.0\n\nAppend the specified buffer to the string 'str'. The string must be a\nstring created by the user that is referenced only a single time, otherwise\n`REDISMODULE_ERR` is returned and the operation is not performed.\n\n<span id=\"RedisModule_TrimStringAllocation\"></span>"
    },
    {
      "id": "redismodule-trimstringallocation",
      "title": "`RedisModule_TrimStringAllocation`",
      "role": "content",
      "text": "void RedisModule_TrimStringAllocation(RedisModuleString *str);\n\n**Available since:** 7.0.0\n\nTrim possible excess memory allocated for a `RedisModuleString`.\n\nSometimes a `RedisModuleString` may have more memory allocated for\nit than required, typically for argv arguments that were constructed\nfrom network buffers. This function optimizes such strings by reallocating\ntheir memory, which is useful for strings that are not short lived but\nretained for an extended duration.\n\nThis operation is *not thread safe* and should only be called when\nno concurrent access to the string is guaranteed. Using it for an argv\nstring in a module command before the string is potentially available\nto other threads is generally safe.\n\nCurrently, Redis may also automatically trim retained strings when a\nmodule command returns. However, doing this explicitly should still be\na preferred option:\n\n1. Future versions of Redis may abandon auto-trimming.\n2. Auto-trimming as currently implemented is *not thread safe*.\n   A background thread manipulating a recently retained string may end up\n   in a race condition with the auto-trim, which could result with\n   data corruption.\n\n<span id=\"section-reply-apis\"></span>"
    },
    {
      "id": "reply-apis",
      "title": "Reply APIs",
      "role": "content",
      "text": "These functions are used for sending replies to the client.\n\nMost functions always return `REDISMODULE_OK` so you can use it with\n'return' in order to return from the command implementation with:\n\n    if (... some condition ...)\n        return RedisModule_ReplyWithLongLong(ctx,mycount);"
    },
    {
      "id": "reply-with-collection-functions",
      "title": "Reply with collection functions",
      "role": "content",
      "text": "After starting a collection reply, the module must make calls to other\n`ReplyWith*` style functions in order to emit the elements of the collection.\nCollection types include: Array, Map, Set and Attribute.\n\nWhen producing collections with a number of elements that is not known\nbeforehand, the function can be called with a special flag\n`REDISMODULE_POSTPONED_LEN` (`REDISMODULE_POSTPONED_ARRAY_LEN` in the past),\nand the actual number of elements can be later set with `RedisModule_ReplySet`*Length()\ncall (which will set the latest \"open\" count if there are multiple ones).\n\n<span id=\"RedisModule_WrongArity\"></span>"
    },
    {
      "id": "redismodule-wrongarity",
      "title": "`RedisModule_WrongArity`",
      "role": "content",
      "text": "int RedisModule_WrongArity(RedisModuleCtx *ctx);\n\n**Available since:** 4.0.0\n\nSend an error about the number of arguments given to the command,\nciting the command name in the error message. Returns `REDISMODULE_OK`.\n\nExample:\n\n    if (argc != 3) return RedisModule_WrongArity(ctx);\n\n<span id=\"RedisModule_ReplyWithLongLong\"></span>"
    },
    {
      "id": "redismodule-replywithlonglong",
      "title": "`RedisModule_ReplyWithLongLong`",
      "role": "content",
      "text": "int RedisModule_ReplyWithLongLong(RedisModuleCtx *ctx, long long ll);\n\n**Available since:** 4.0.0\n\nSend an integer reply to the client, with the specified `long long` value.\nThe function always returns `REDISMODULE_OK`.\n\n<span id=\"RedisModule_ReplyWithError\"></span>"
    },
    {
      "id": "redismodule-replywitherror",
      "title": "`RedisModule_ReplyWithError`",
      "role": "content",
      "text": "int RedisModule_ReplyWithError(RedisModuleCtx *ctx, const char *err);\n\n**Available since:** 4.0.0\n\nReply with the error 'err'.\n\nNote that 'err' must contain all the error, including\nthe initial error code. The function only provides the initial \"-\", so\nthe usage is, for example:\n\n    RedisModule_ReplyWithError(ctx,\"ERR Wrong Type\");\n\nand not just:\n\n    RedisModule_ReplyWithError(ctx,\"Wrong Type\");\n\nThe function always returns `REDISMODULE_OK`.\n\n<span id=\"RedisModule_ReplyWithErrorFormat\"></span>"
    },
    {
      "id": "redismodule-replywitherrorformat",
      "title": "`RedisModule_ReplyWithErrorFormat`",
      "role": "content",
      "text": "int RedisModule_ReplyWithErrorFormat(RedisModuleCtx *ctx,\n                                         const char *fmt,\n                                         ...);\n\n**Available since:** 7.2.0\n\nReply with the error create from a printf format and arguments.\n\nNote that 'fmt' must contain all the error, including\nthe initial error code. The function only provides the initial \"-\", so\nthe usage is, for example:\n\n    RedisModule_ReplyWithErrorFormat(ctx,\"ERR Wrong Type: %s\",type);\n\nand not just:\n\n    RedisModule_ReplyWithErrorFormat(ctx,\"Wrong Type: %s\",type);\n\nThe function always returns `REDISMODULE_OK`.\n\n<span id=\"RedisModule_ReplyWithSimpleString\"></span>"
    },
    {
      "id": "redismodule-replywithsimplestring",
      "title": "`RedisModule_ReplyWithSimpleString`",
      "role": "content",
      "text": "int RedisModule_ReplyWithSimpleString(RedisModuleCtx *ctx, const char *msg);\n\n**Available since:** 4.0.0\n\nReply with a simple string (`+... \\r\\n` in RESP protocol). This replies\nare suitable only when sending a small non-binary string with small\noverhead, like \"OK\" or similar replies.\n\nThe function always returns `REDISMODULE_OK`.\n\n<span id=\"RedisModule_ReplyWithArray\"></span>"
    },
    {
      "id": "redismodule-replywitharray",
      "title": "`RedisModule_ReplyWithArray`",
      "role": "content",
      "text": "int RedisModule_ReplyWithArray(RedisModuleCtx *ctx, long len);\n\n**Available since:** 4.0.0\n\nReply with an array type of 'len' elements.\n\nAfter starting an array reply, the module must make `len` calls to other\n`ReplyWith*` style functions in order to emit the elements of the array.\nSee Reply APIs section for more details.\n\nUse [`RedisModule_ReplySetArrayLength()`](#RedisModule_ReplySetArrayLength) to set deferred length.\n\nThe function always returns `REDISMODULE_OK`.\n\n<span id=\"RedisModule_ReplyWithMap\"></span>"
    },
    {
      "id": "redismodule-replywithmap",
      "title": "`RedisModule_ReplyWithMap`",
      "role": "content",
      "text": "int RedisModule_ReplyWithMap(RedisModuleCtx *ctx, long len);\n\n**Available since:** 7.0.0\n\nReply with a RESP3 Map type of 'len' pairs.\nVisit [https://github.com/antirez/RESP3/blob/master/spec.md](https://github.com/antirez/RESP3/blob/master/spec.md) for more info about RESP3.\n\nAfter starting a map reply, the module must make `len*2` calls to other\n`ReplyWith*` style functions in order to emit the elements of the map.\nSee Reply APIs section for more details.\n\nIf the connected client is using RESP2, the reply will be converted to a flat\narray.\n\nUse [`RedisModule_ReplySetMapLength()`](#RedisModule_ReplySetMapLength) to set deferred length.\n\nThe function always returns `REDISMODULE_OK`.\n\n<span id=\"RedisModule_ReplyWithSet\"></span>"
    },
    {
      "id": "redismodule-replywithset",
      "title": "`RedisModule_ReplyWithSet`",
      "role": "content",
      "text": "int RedisModule_ReplyWithSet(RedisModuleCtx *ctx, long len);\n\n**Available since:** 7.0.0\n\nReply with a RESP3 Set type of 'len' elements.\nVisit [https://github.com/antirez/RESP3/blob/master/spec.md](https://github.com/antirez/RESP3/blob/master/spec.md) for more info about RESP3.\n\nAfter starting a set reply, the module must make `len` calls to other\n`ReplyWith*` style functions in order to emit the elements of the set.\nSee Reply APIs section for more details.\n\nIf the connected client is using RESP2, the reply will be converted to an\narray type.\n\nUse [`RedisModule_ReplySetSetLength()`](#RedisModule_ReplySetSetLength) to set deferred length.\n\nThe function always returns `REDISMODULE_OK`.\n\n<span id=\"RedisModule_ReplyWithAttribute\"></span>"
    },
    {
      "id": "redismodule-replywithattribute",
      "title": "`RedisModule_ReplyWithAttribute`",
      "role": "content",
      "text": "int RedisModule_ReplyWithAttribute(RedisModuleCtx *ctx, long len);\n\n**Available since:** 7.0.0\n\nAdd attributes (metadata) to the reply. Should be done before adding the\nactual reply. see [https://github.com/antirez/RESP3/blob/master/spec.md](https://github.com/antirez/RESP3/blob/master/spec.md)#attribute-type\n\nAfter starting an attribute's reply, the module must make `len*2` calls to other\n`ReplyWith*` style functions in order to emit the elements of the attribute map.\nSee Reply APIs section for more details.\n\nUse [`RedisModule_ReplySetAttributeLength()`](#RedisModule_ReplySetAttributeLength) to set deferred length.\n\nNot supported by RESP2 and will return `REDISMODULE_ERR`, otherwise\nthe function always returns `REDISMODULE_OK`.\n\n<span id=\"RedisModule_ReplyWithNullArray\"></span>"
    },
    {
      "id": "redismodule-replywithnullarray",
      "title": "`RedisModule_ReplyWithNullArray`",
      "role": "content",
      "text": "int RedisModule_ReplyWithNullArray(RedisModuleCtx *ctx);\n\n**Available since:** 6.0.0\n\nReply to the client with a null array, simply null in RESP3,\nnull array in RESP2.\n\nNote: In RESP3 there's no difference between Null reply and\nNullArray reply, so to prevent ambiguity it's better to avoid\nusing this API and use [`RedisModule_ReplyWithNull`](#RedisModule_ReplyWithNull) instead.\n\nThe function always returns `REDISMODULE_OK`.\n\n<span id=\"RedisModule_ReplyWithEmptyArray\"></span>"
    },
    {
      "id": "redismodule-replywithemptyarray",
      "title": "`RedisModule_ReplyWithEmptyArray`",
      "role": "content",
      "text": "int RedisModule_ReplyWithEmptyArray(RedisModuleCtx *ctx);\n\n**Available since:** 6.0.0\n\nReply to the client with an empty array.\n\nThe function always returns `REDISMODULE_OK`.\n\n<span id=\"RedisModule_ReplySetArrayLength\"></span>"
    },
    {
      "id": "redismodule-replysetarraylength",
      "title": "`RedisModule_ReplySetArrayLength`",
      "role": "content",
      "text": "void RedisModule_ReplySetArrayLength(RedisModuleCtx *ctx, long len);\n\n**Available since:** 4.0.0\n\nWhen [`RedisModule_ReplyWithArray()`](#RedisModule_ReplyWithArray) is used with the argument\n`REDISMODULE_POSTPONED_LEN`, because we don't know beforehand the number\nof items we are going to output as elements of the array, this function\nwill take care to set the array length.\n\nSince it is possible to have multiple array replies pending with unknown\nlength, this function guarantees to always set the latest array length\nthat was created in a postponed way.\n\nFor example in order to output an array like [1,[10,20,30]] we\ncould write:\n\n     RedisModule_ReplyWithArray(ctx,REDISMODULE_POSTPONED_LEN);\n     RedisModule_ReplyWithLongLong(ctx,1);\n     RedisModule_ReplyWithArray(ctx,REDISMODULE_POSTPONED_LEN);\n     RedisModule_ReplyWithLongLong(ctx,10);\n     RedisModule_ReplyWithLongLong(ctx,20);\n     RedisModule_ReplyWithLongLong(ctx,30);\n     RedisModule_ReplySetArrayLength(ctx,3); // Set len of 10,20,30 array.\n     RedisModule_ReplySetArrayLength(ctx,2); // Set len of top array\n\nNote that in the above example there is no reason to postpone the array\nlength, since we produce a fixed number of elements, but in the practice\nthe code may use an iterator or other ways of creating the output so\nthat is not easy to calculate in advance the number of elements.\n\n<span id=\"RedisModule_ReplySetMapLength\"></span>"
    },
    {
      "id": "redismodule-replysetmaplength",
      "title": "`RedisModule_ReplySetMapLength`",
      "role": "content",
      "text": "void RedisModule_ReplySetMapLength(RedisModuleCtx *ctx, long len);\n\n**Available since:** 7.0.0\n\nVery similar to [`RedisModule_ReplySetArrayLength`](#RedisModule_ReplySetArrayLength) except `len` should\nexactly half of the number of `ReplyWith*` functions called in the\ncontext of the map.\nVisit [https://github.com/antirez/RESP3/blob/master/spec.md](https://github.com/antirez/RESP3/blob/master/spec.md) for more info about RESP3.\n\n<span id=\"RedisModule_ReplySetSetLength\"></span>"
    },
    {
      "id": "redismodule-replysetsetlength",
      "title": "`RedisModule_ReplySetSetLength`",
      "role": "content",
      "text": "void RedisModule_ReplySetSetLength(RedisModuleCtx *ctx, long len);\n\n**Available since:** 7.0.0\n\nVery similar to [`RedisModule_ReplySetArrayLength`](#RedisModule_ReplySetArrayLength)\nVisit [https://github.com/antirez/RESP3/blob/master/spec.md](https://github.com/antirez/RESP3/blob/master/spec.md) for more info about RESP3.\n\n<span id=\"RedisModule_ReplySetAttributeLength\"></span>"
    },
    {
      "id": "redismodule-replysetattributelength",
      "title": "`RedisModule_ReplySetAttributeLength`",
      "role": "content",
      "text": "void RedisModule_ReplySetAttributeLength(RedisModuleCtx *ctx, long len);\n\n**Available since:** 7.0.0\n\nVery similar to [`RedisModule_ReplySetMapLength`](#RedisModule_ReplySetMapLength)\nVisit [https://github.com/antirez/RESP3/blob/master/spec.md](https://github.com/antirez/RESP3/blob/master/spec.md) for more info about RESP3.\n\nMust not be called if [`RedisModule_ReplyWithAttribute`](#RedisModule_ReplyWithAttribute) returned an error.\n\n<span id=\"RedisModule_ReplyWithStringBuffer\"></span>"
    },
    {
      "id": "redismodule-replywithstringbuffer",
      "title": "`RedisModule_ReplyWithStringBuffer`",
      "role": "content",
      "text": "int RedisModule_ReplyWithStringBuffer(RedisModuleCtx *ctx,\n                                          const char *buf,\n                                          size_t len);\n\n**Available since:** 4.0.0\n\nReply with a bulk string, taking in input a C buffer pointer and length.\n\nThe function always returns `REDISMODULE_OK`.\n\n<span id=\"RedisModule_ReplyWithCString\"></span>"
    },
    {
      "id": "redismodule-replywithcstring",
      "title": "`RedisModule_ReplyWithCString`",
      "role": "content",
      "text": "int RedisModule_ReplyWithCString(RedisModuleCtx *ctx, const char *buf);\n\n**Available since:** 5.0.6\n\nReply with a bulk string, taking in input a C buffer pointer that is\nassumed to be null-terminated.\n\nThe function always returns `REDISMODULE_OK`.\n\n<span id=\"RedisModule_ReplyWithString\"></span>"
    },
    {
      "id": "redismodule-replywithstring",
      "title": "`RedisModule_ReplyWithString`",
      "role": "content",
      "text": "int RedisModule_ReplyWithString(RedisModuleCtx *ctx, RedisModuleString *str);\n\n**Available since:** 4.0.0\n\nReply with a bulk string, taking in input a `RedisModuleString` object.\n\nThe function always returns `REDISMODULE_OK`.\n\n<span id=\"RedisModule_ReplyWithEmptyString\"></span>"
    },
    {
      "id": "redismodule-replywithemptystring",
      "title": "`RedisModule_ReplyWithEmptyString`",
      "role": "content",
      "text": "int RedisModule_ReplyWithEmptyString(RedisModuleCtx *ctx);\n\n**Available since:** 6.0.0\n\nReply with an empty string.\n\nThe function always returns `REDISMODULE_OK`.\n\n<span id=\"RedisModule_ReplyWithVerbatimStringType\"></span>"
    },
    {
      "id": "redismodule-replywithverbatimstringtype",
      "title": "`RedisModule_ReplyWithVerbatimStringType`",
      "role": "content",
      "text": "int RedisModule_ReplyWithVerbatimStringType(RedisModuleCtx *ctx,\n                                                const char *buf,\n                                                size_t len,\n                                                const char *ext);\n\n**Available since:** 7.0.0\n\nReply with a binary safe string, which should not be escaped or filtered\ntaking in input a C buffer pointer, length and a 3 character type/extension.\n\nThe function always returns `REDISMODULE_OK`.\n\n<span id=\"RedisModule_ReplyWithVerbatimString\"></span>"
    },
    {
      "id": "redismodule-replywithverbatimstring",
      "title": "`RedisModule_ReplyWithVerbatimString`",
      "role": "content",
      "text": "int RedisModule_ReplyWithVerbatimString(RedisModuleCtx *ctx,\n                                            const char *buf,\n                                            size_t len);\n\n**Available since:** 6.0.0\n\nReply with a binary safe string, which should not be escaped or filtered\ntaking in input a C buffer pointer and length.\n\nThe function always returns `REDISMODULE_OK`.\n\n<span id=\"RedisModule_ReplyWithNull\"></span>"
    },
    {
      "id": "redismodule-replywithnull",
      "title": "`RedisModule_ReplyWithNull`",
      "role": "content",
      "text": "int RedisModule_ReplyWithNull(RedisModuleCtx *ctx);\n\n**Available since:** 4.0.0\n\nReply to the client with a NULL.\n\nThe function always returns `REDISMODULE_OK`.\n\n<span id=\"RedisModule_ReplyWithBool\"></span>"
    },
    {
      "id": "redismodule-replywithbool",
      "title": "`RedisModule_ReplyWithBool`",
      "role": "content",
      "text": "int RedisModule_ReplyWithBool(RedisModuleCtx *ctx, int b);\n\n**Available since:** 7.0.0\n\nReply with a RESP3 Boolean type.\nVisit [https://github.com/antirez/RESP3/blob/master/spec.md](https://github.com/antirez/RESP3/blob/master/spec.md) for more info about RESP3.\n\nIn RESP3, this is boolean type\nIn RESP2, it's a string response of \"1\" and \"0\" for true and false respectively.\n\nThe function always returns `REDISMODULE_OK`.\n\n<span id=\"RedisModule_ReplyWithCallReply\"></span>"
    },
    {
      "id": "redismodule-replywithcallreply",
      "title": "`RedisModule_ReplyWithCallReply`",
      "role": "content",
      "text": "int RedisModule_ReplyWithCallReply(RedisModuleCtx *ctx,\n                                       RedisModuleCallReply *reply);\n\n**Available since:** 4.0.0\n\nReply exactly what a Redis command returned us with [`RedisModule_Call()`](#RedisModule_Call).\nThis function is useful when we use [`RedisModule_Call()`](#RedisModule_Call) in order to\nexecute some command, as we want to reply to the client exactly the\nsame reply we obtained by the command.\n\nReturn:\n- `REDISMODULE_OK` on success.\n- `REDISMODULE_ERR` if the given reply is in RESP3 format but the client expects RESP2.\n  In case of an error, it's the module writer responsibility to translate the reply\n  to RESP2 (or handle it differently by returning an error). Notice that for\n  module writer convenience, it is possible to pass `0` as a parameter to the fmt\n  argument of [`RedisModule_Call`](#RedisModule_Call) so that the `RedisModuleCallReply` will return in the same\n  protocol (RESP2 or RESP3) as set in the current client's context.\n\n<span id=\"RedisModule_ReplyWithDouble\"></span>"
    },
    {
      "id": "redismodule-replywithdouble",
      "title": "`RedisModule_ReplyWithDouble`",
      "role": "content",
      "text": "int RedisModule_ReplyWithDouble(RedisModuleCtx *ctx, double d);\n\n**Available since:** 4.0.0\n\nReply with a RESP3 Double type.\nVisit [https://github.com/antirez/RESP3/blob/master/spec.md](https://github.com/antirez/RESP3/blob/master/spec.md) for more info about RESP3.\n\nSend a string reply obtained converting the double 'd' into a bulk string.\nThis function is basically equivalent to converting a double into\na string into a C buffer, and then calling the function\n[`RedisModule_ReplyWithStringBuffer()`](#RedisModule_ReplyWithStringBuffer) with the buffer and length.\n\nIn RESP3 the string is tagged as a double, while in RESP2 it's just a plain string \nthat the user will have to parse.\n\nThe function always returns `REDISMODULE_OK`.\n\n<span id=\"RedisModule_ReplyWithBigNumber\"></span>"
    },
    {
      "id": "redismodule-replywithbignumber",
      "title": "`RedisModule_ReplyWithBigNumber`",
      "role": "content",
      "text": "int RedisModule_ReplyWithBigNumber(RedisModuleCtx *ctx,\n                                       const char *bignum,\n                                       size_t len);\n\n**Available since:** 7.0.0\n\nReply with a RESP3 BigNumber type.\nVisit [https://github.com/antirez/RESP3/blob/master/spec.md](https://github.com/antirez/RESP3/blob/master/spec.md) for more info about RESP3.\n\nIn RESP3, this is a string of length `len` that is tagged as a BigNumber, \nhowever, it's up to the caller to ensure that it's a valid BigNumber.\nIn RESP2, this is just a plain bulk string response.\n\nThe function always returns `REDISMODULE_OK`.\n\n<span id=\"RedisModule_ReplyWithLongDouble\"></span>"
    },
    {
      "id": "redismodule-replywithlongdouble",
      "title": "`RedisModule_ReplyWithLongDouble`",
      "role": "content",
      "text": "int RedisModule_ReplyWithLongDouble(RedisModuleCtx *ctx, long double ld);\n\n**Available since:** 6.0.0\n\nSend a string reply obtained converting the long double 'ld' into a bulk\nstring. This function is basically equivalent to converting a long double\ninto a string into a C buffer, and then calling the function\n[`RedisModule_ReplyWithStringBuffer()`](#RedisModule_ReplyWithStringBuffer) with the buffer and length.\nThe double string uses human readable formatting (see\n`addReplyHumanLongDouble` in networking.c).\n\nThe function always returns `REDISMODULE_OK`.\n\n<span id=\"section-commands-replication-api\"></span>"
    },
    {
      "id": "commands-replication-api",
      "title": "Commands replication API",
      "role": "syntax",
      "text": "<span id=\"RedisModule_Replicate\"></span>"
    },
    {
      "id": "redismodule-replicate",
      "title": "`RedisModule_Replicate`",
      "role": "content",
      "text": "int RedisModule_Replicate(RedisModuleCtx *ctx,\n                              const char *cmdname,\n                              const char *fmt,\n                              ...);\n\n**Available since:** 4.0.0\n\nReplicate the specified command and arguments to slaves and AOF, as effect\nof execution of the calling command implementation.\n\nThe replicated commands are always wrapped into the MULTI/EXEC that\ncontains all the commands replicated in a given module command\nexecution, in the order they were executed.\n\nModules should try to use one interface or the other.\n\nThis command follows exactly the same interface of [`RedisModule_Call()`](#RedisModule_Call),\nso a set of format specifiers must be passed, followed by arguments\nmatching the provided format specifiers.\n\nPlease refer to [`RedisModule_Call()`](#RedisModule_Call) for more information.\n\nUsing the special \"A\" and \"R\" modifiers, the caller can exclude either\nthe AOF or the replicas from the propagation of the specified command.\nOtherwise, by default, the command will be propagated in both channels.\n\n#### Note about calling this function from a thread safe context:\n\nNormally when you call this function from the callback implementing a\nmodule command, or any other callback provided by the Redis Module API,\nRedis will accumulate all the calls to this function in the context of\nthe callback, and will propagate all the commands wrapped in a MULTI/EXEC\ntransaction. However when calling this function from a threaded safe context\nthat can live an undefined amount of time, and can be locked/unlocked in\nat will, it is important to note that this API is not thread-safe and\nmust be executed while holding the GIL.\n\n#### Return value\n\nThe command returns `REDISMODULE_ERR` if the format specifiers are invalid\nor the command name does not belong to a known command.\n\n<span id=\"RedisModule_ReplicateVerbatim\"></span>"
    },
    {
      "id": "redismodule-replicateverbatim",
      "title": "`RedisModule_ReplicateVerbatim`",
      "role": "content",
      "text": "int RedisModule_ReplicateVerbatim(RedisModuleCtx *ctx);\n\n**Available since:** 4.0.0\n\nThis function will replicate the command exactly as it was invoked\nby the client. Note that the replicated commands are always wrapped\ninto the MULTI/EXEC that contains all the commands replicated in a\ngiven module command execution, in the order they were executed.\n\nBasically this form of replication is useful when you want to propagate\nthe command to the slaves and AOF file exactly as it was called, since\nthe command can just be re-executed to deterministically re-create the\nnew state starting from the old one.\n\nIt is important to note that this API is not thread-safe and\nmust be executed while holding the GIL.\n\nThe function always returns `REDISMODULE_OK`.\n\n<span id=\"section-db-and-key-apis-generic-api\"></span>"
    },
    {
      "id": "db-and-key-apis-generic-api",
      "title": "DB and Key APIs – Generic API",
      "role": "content",
      "text": "<span id=\"RedisModule_GetClientId\"></span>"
    },
    {
      "id": "redismodule-getclientid",
      "title": "`RedisModule_GetClientId`",
      "role": "content",
      "text": "unsigned long long RedisModule_GetClientId(RedisModuleCtx *ctx);\n\n**Available since:** 4.0.0\n\nReturn the ID of the current client calling the currently active module\ncommand. The returned ID has a few guarantees:\n\n1. The ID is different for each different client, so if the same client\n   executes a module command multiple times, it can be recognized as\n   having the same ID, otherwise the ID will be different.\n2. The ID increases monotonically. Clients connecting to the server later\n   are guaranteed to get IDs greater than any past ID previously seen.\n\nValid IDs are from 1 to 2^64 - 1. If 0 is returned it means there is no way\nto fetch the ID in the context the function was currently called.\n\nAfter obtaining the ID, it is possible to check if the command execution\nis actually happening in the context of AOF loading, using this macro:\n\n     if (RedisModule_IsAOFClient(RedisModule_GetClientId(ctx)) {\n         // Handle it differently.\n     }\n\n<span id=\"RedisModule_GetClientUserNameById\"></span>"
    },
    {
      "id": "redismodule-getclientusernamebyid",
      "title": "`RedisModule_GetClientUserNameById`",
      "role": "content",
      "text": "RedisModuleString *RedisModule_GetClientUserNameById(RedisModuleCtx *ctx,\n                                                         uint64_t id);\n\n**Available since:** 6.2.1\n\nReturn the ACL user name used by the client with the specified client ID.\nClient ID can be obtained with [`RedisModule_GetClientId()`](#RedisModule_GetClientId) API. If the client does not\nexist, NULL is returned and errno is set to ENOENT. If the client isn't\nusing an ACL user, NULL is returned and errno is set to ENOTSUP\n\n<span id=\"RedisModule_GetClientInfoById\"></span>"
    },
    {
      "id": "redismodule-getclientinfobyid",
      "title": "`RedisModule_GetClientInfoById`",
      "role": "content",
      "text": "int RedisModule_GetClientInfoById(void *ci, uint64_t id);\n\n**Available since:** 6.0.0\n\nReturn information about the client with the specified ID (that was\npreviously obtained via the [`RedisModule_GetClientId()`](#RedisModule_GetClientId) API). If the\nclient exists, `REDISMODULE_OK` is returned, otherwise `REDISMODULE_ERR`\nis returned.\n\nWhen the client exist and the `ci` pointer is not NULL, but points to\na structure of type `RedisModuleClientInfoV`1, previously initialized with\nthe correct `REDISMODULE_CLIENTINFO_INITIALIZER_V1`, the structure is populated\nwith the following fields:\n\n     uint64_t flags;         // REDISMODULE_CLIENTINFO_FLAG_*\n     uint64_t id;            // Client ID\n     char addr[46];          // IPv4 or IPv6 address.\n     uint16_t port;          // TCP port.\n     uint16_t db;            // Selected DB.\n\nNote: the client ID is useless in the context of this call, since we\n      already know, however the same structure could be used in other\n      contexts where we don't know the client ID, yet the same structure\n      is returned.\n\nWith flags having the following meaning:\n\n    REDISMODULE_CLIENTINFO_FLAG_SSL          Client using SSL connection.\n    REDISMODULE_CLIENTINFO_FLAG_PUBSUB       Client in Pub/Sub mode.\n    REDISMODULE_CLIENTINFO_FLAG_BLOCKED      Client blocked in command.\n    REDISMODULE_CLIENTINFO_FLAG_TRACKING     Client with keys tracking on.\n    REDISMODULE_CLIENTINFO_FLAG_UNIXSOCKET   Client using unix domain socket.\n    REDISMODULE_CLIENTINFO_FLAG_MULTI        Client in MULTI state.\n\nHowever passing NULL is a way to just check if the client exists in case\nwe are not interested in any additional information.\n\nThis is the correct usage when we want the client info structure\nreturned:\n\n     RedisModuleClientInfo ci = REDISMODULE_CLIENTINFO_INITIALIZER;\n     int retval = RedisModule_GetClientInfoById(&ci,client_id);\n     if (retval == REDISMODULE_OK) {\n         printf(\"Address: %s\\n\", ci.addr);\n     }\n\n<span id=\"RedisModule_GetClientNameById\"></span>"
    },
    {
      "id": "redismodule-getclientnamebyid",
      "title": "`RedisModule_GetClientNameById`",
      "role": "content",
      "text": "RedisModuleString *RedisModule_GetClientNameById(RedisModuleCtx *ctx,\n                                                     uint64_t id);\n\n**Available since:** 7.0.3\n\nReturns the name of the client connection with the given ID.\n\nIf the client ID does not exist or if the client has no name associated with\nit, NULL is returned.\n\n<span id=\"RedisModule_SetClientNameById\"></span>"
    },
    {
      "id": "redismodule-setclientnamebyid",
      "title": "`RedisModule_SetClientNameById`",
      "role": "content",
      "text": "int RedisModule_SetClientNameById(uint64_t id, RedisModuleString *name);\n\n**Available since:** 7.0.3\n\nSets the name of the client with the given ID. This is equivalent to the client calling\n`CLIENT SETNAME name`.\n\nReturns `REDISMODULE_OK` on success. On failure, `REDISMODULE_ERR` is returned\nand errno is set as follows:\n\n- ENOENT if the client does not exist\n- EINVAL if the name contains invalid characters\n\n<span id=\"RedisModule_PublishMessage\"></span>"
    },
    {
      "id": "redismodule-publishmessage",
      "title": "`RedisModule_PublishMessage`",
      "role": "content",
      "text": "int RedisModule_PublishMessage(RedisModuleCtx *ctx,\n                                   RedisModuleString *channel,\n                                   RedisModuleString *message);\n\n**Available since:** 6.0.0\n\nPublish a message to subscribers (see PUBLISH command).\n\n<span id=\"RedisModule_PublishMessageShard\"></span>"
    },
    {
      "id": "redismodule-publishmessageshard",
      "title": "`RedisModule_PublishMessageShard`",
      "role": "content",
      "text": "int RedisModule_PublishMessageShard(RedisModuleCtx *ctx,\n                                        RedisModuleString *channel,\n                                        RedisModuleString *message);\n\n**Available since:** 7.0.0\n\nPublish a message to shard-subscribers (see SPUBLISH command).\n\n<span id=\"RedisModule_GetSelectedDb\"></span>"
    },
    {
      "id": "redismodule-getselecteddb",
      "title": "`RedisModule_GetSelectedDb`",
      "role": "content",
      "text": "int RedisModule_GetSelectedDb(RedisModuleCtx *ctx);\n\n**Available since:** 4.0.0\n\nReturn the currently selected DB.\n\n<span id=\"RedisModule_GetContextFlags\"></span>"
    },
    {
      "id": "redismodule-getcontextflags",
      "title": "`RedisModule_GetContextFlags`",
      "role": "content",
      "text": "int RedisModule_GetContextFlags(RedisModuleCtx *ctx);\n\n**Available since:** 4.0.3\n\nReturn the current context's flags. The flags provide information on the\ncurrent request context (whether the client is a Lua script or in a MULTI),\nand about the Redis instance in general, i.e replication and persistence.\n\nIt is possible to call this function even with a NULL context, however\nin this case the following flags will not be reported:\n\n * LUA, MULTI, REPLICATED, DIRTY (see below for more info).\n\nAvailable flags and their meaning:\n\n * `REDISMODULE_CTX_FLAGS_LUA`: The command is running in a Lua script\n\n * `REDISMODULE_CTX_FLAGS_MULTI`: The command is running inside a transaction\n\n * `REDISMODULE_CTX_FLAGS_REPLICATED`: The command was sent over the replication\n   link by the MASTER\n\n * `REDISMODULE_CTX_FLAGS_MASTER`: The Redis instance is a master\n\n * `REDISMODULE_CTX_FLAGS_SLAVE`: The Redis instance is a slave\n\n * `REDISMODULE_CTX_FLAGS_READONLY`: The Redis instance is read-only\n\n * `REDISMODULE_CTX_FLAGS_CLUSTER`: The Redis instance is in cluster mode\n\n * `REDISMODULE_CTX_FLAGS_AOF`: The Redis instance has AOF enabled\n\n * `REDISMODULE_CTX_FLAGS_RDB`: The instance has RDB enabled\n\n * `REDISMODULE_CTX_FLAGS_MAXMEMORY`:  The instance has Maxmemory set\n\n * `REDISMODULE_CTX_FLAGS_EVICT`:  Maxmemory is set and has an eviction\n   policy that may delete keys\n\n * `REDISMODULE_CTX_FLAGS_OOM`: Redis is out of memory according to the\n   maxmemory setting.\n\n * `REDISMODULE_CTX_FLAGS_OOM_WARNING`: Less than 25% of memory remains before\n                                      reaching the maxmemory level.\n\n * `REDISMODULE_CTX_FLAGS_LOADING`: Server is loading RDB/AOF\n\n * `REDISMODULE_CTX_FLAGS_REPLICA_IS_STALE`: No active link with the master.\n\n * `REDISMODULE_CTX_FLAGS_REPLICA_IS_CONNECTING`: The replica is trying to\n                                                connect with the master.\n\n * `REDISMODULE_CTX_FLAGS_REPLICA_IS_TRANSFERRING`: Master -> Replica RDB\n                                                  transfer is in progress.\n\n * `REDISMODULE_CTX_FLAGS_REPLICA_IS_ONLINE`: The replica has an active link\n                                            with its master. This is the\n                                            contrary of STALE state.\n\n * `REDISMODULE_CTX_FLAGS_ACTIVE_CHILD`: There is currently some background\n                                       process active (RDB, AUX or module).\n\n * `REDISMODULE_CTX_FLAGS_MULTI_DIRTY`: The next EXEC will fail due to dirty\n                                      CAS (touched keys).\n\n * `REDISMODULE_CTX_FLAGS_IS_CHILD`: Redis is currently running inside\n                                   background child process.\n\n * `REDISMODULE_CTX_FLAGS_RESP3`: Indicate the that client attached to this\n                                context is using RESP3.\n\n * `REDISMODULE_CTX_FLAGS_SERVER_STARTUP`: The Redis instance is starting\n\n * `REDISMODULE_CTX_FLAGS_DEBUG_ENABLED`: Debug commands are enabled for this\n                                        context.\n * `REDISMODULE_CTX_FLAGS_TRIM_IN_PROGRESS`: Trim is in progress due to slot\n                                           migration.\n\n<span id=\"RedisModule_AvoidReplicaTraffic\"></span>"
    },
    {
      "id": "redismodule-avoidreplicatraffic",
      "title": "`RedisModule_AvoidReplicaTraffic`",
      "role": "content",
      "text": "int RedisModule_AvoidReplicaTraffic(void);\n\n**Available since:** 6.0.0\n\nReturns true if a client sent the CLIENT PAUSE command to the server or\nif Redis Cluster does a manual failover, pausing the clients.\nThis is needed when we have a master with replicas, and want to write,\nwithout adding further data to the replication channel, that the replicas\nreplication offset, match the one of the master. When this happens, it is\nsafe to failover the master without data loss.\n\nHowever modules may generate traffic by calling [`RedisModule_Call()`](#RedisModule_Call) with\nthe \"!\" flag, or by calling [`RedisModule_Replicate()`](#RedisModule_Replicate), in a context outside\ncommands execution, for instance in timeout callbacks, threads safe\ncontexts, and so forth. When modules will generate too much traffic, it\nwill be hard for the master and replicas offset to match, because there\nis more data to send in the replication channel.\n\nSo modules may want to try to avoid very heavy background work that has\nthe effect of creating data to the replication channel, when this function\nreturns true. This is mostly useful for modules that have background\ngarbage collection tasks, or that do writes and replicate such writes\nperiodically in timer callbacks or other periodic callbacks.\n\n<span id=\"RedisModule_SelectDb\"></span>"
    },
    {
      "id": "redismodule-selectdb",
      "title": "`RedisModule_SelectDb`",
      "role": "content",
      "text": "int RedisModule_SelectDb(RedisModuleCtx *ctx, int newid);\n\n**Available since:** 4.0.0\n\nChange the currently selected DB. Returns an error if the id\nis out of range.\n\nNote that the client will retain the currently selected DB even after\nthe Redis command implemented by the module calling this function\nreturns.\n\nIf the module command wishes to change something in a different DB and\nreturns back to the original one, it should call [`RedisModule_GetSelectedDb()`](#RedisModule_GetSelectedDb)\nbefore in order to restore the old DB number before returning.\n\n<span id=\"RedisModule_KeyExists\"></span>"
    },
    {
      "id": "redismodule-keyexists",
      "title": "`RedisModule_KeyExists`",
      "role": "content",
      "text": "int RedisModule_KeyExists(RedisModuleCtx *ctx, robj *keyname);\n\n**Available since:** 7.0.0\n\nCheck if a key exists, without affecting its last access time.\n\nThis is equivalent to calling [`RedisModule_OpenKey`](#RedisModule_OpenKey) with the mode `REDISMODULE_READ` |\n`REDISMODULE_OPEN_KEY_NOTOUCH`, then checking if NULL was returned and, if not,\ncalling [`RedisModule_CloseKey`](#RedisModule_CloseKey) on the opened key.\n\n<span id=\"RedisModule_OpenKey\"></span>"
    },
    {
      "id": "redismodule-openkey",
      "title": "`RedisModule_OpenKey`",
      "role": "content",
      "text": "RedisModuleKey *RedisModule_OpenKey(RedisModuleCtx *ctx,\n                                        robj *keyname,\n                                        int mode);\n\n**Available since:** 4.0.0\n\nReturn a handle representing a Redis key, so that it is possible\nto call other APIs with the key handle as argument to perform\noperations on the key.\n\nThe return value is the handle representing the key, that must be\nclosed with [`RedisModule_CloseKey()`](#RedisModule_CloseKey).\n\nIf the key does not exist and `REDISMODULE_WRITE` mode is requested, the handle\nis still returned, since it is possible to perform operations on\na yet not existing key (that will be created, for example, after\na list push operation). If the mode is just `REDISMODULE_READ` instead, and the\nkey does not exist, NULL is returned. However it is still safe to\ncall [`RedisModule_CloseKey()`](#RedisModule_CloseKey) and [`RedisModule_KeyType()`](#RedisModule_KeyType) on a NULL\nvalue.\n\nExtra flags that can be pass to the API under the mode argument:\n* `REDISMODULE_OPEN_KEY_NOTOUCH` - Avoid touching the LRU/LFU of the key when opened.\n* `REDISMODULE_OPEN_KEY_NONOTIFY` - Don't trigger keyspace event on key misses.\n* `REDISMODULE_OPEN_KEY_NOSTATS` - Don't update keyspace hits/misses counters.\n* `REDISMODULE_OPEN_KEY_NOEXPIRE` - Avoid deleting lazy expired keys.\n* `REDISMODULE_OPEN_KEY_NOEFFECTS` - Avoid any effects from fetching the key.\n* `REDISMODULE_OPEN_KEY_ACCESS_EXPIRED` - Access expired keys that have not yet been deleted\n\n<span id=\"RedisModule_GetOpenKeyModesAll\"></span>"
    },
    {
      "id": "redismodule-getopenkeymodesall",
      "title": "`RedisModule_GetOpenKeyModesAll`",
      "role": "content",
      "text": "int RedisModule_GetOpenKeyModesAll(void);\n\n**Available since:** 7.2.0\n\n\nReturns the full OpenKey modes mask, using the return value\nthe module can check if a certain set of OpenKey modes are supported\nby the redis server version in use.\nExample:\n\n       int supportedMode = RedisModule_GetOpenKeyModesAll();\n       if (supportedMode & REDISMODULE_OPEN_KEY_NOTOUCH) {\n             // REDISMODULE_OPEN_KEY_NOTOUCH is supported\n       } else{\n             // REDISMODULE_OPEN_KEY_NOTOUCH is not supported\n       }\n\n<span id=\"RedisModule_CloseKey\"></span>"
    },
    {
      "id": "redismodule-closekey",
      "title": "`RedisModule_CloseKey`",
      "role": "content",
      "text": "void RedisModule_CloseKey(RedisModuleKey *key);\n\n**Available since:** 4.0.0\n\nClose a key handle.\n\n<span id=\"RedisModule_KeyType\"></span>"
    },
    {
      "id": "redismodule-keytype",
      "title": "`RedisModule_KeyType`",
      "role": "content",
      "text": "int RedisModule_KeyType(RedisModuleKey *key);\n\n**Available since:** 4.0.0\n\nReturn the type of the key. If the key pointer is NULL then\n`REDISMODULE_KEYTYPE_EMPTY` is returned.\n\n<span id=\"RedisModule_ValueLength\"></span>"
    },
    {
      "id": "redismodule-valuelength",
      "title": "`RedisModule_ValueLength`",
      "role": "content",
      "text": "size_t RedisModule_ValueLength(RedisModuleKey *key);\n\n**Available since:** 4.0.0\n\nReturn the length of the value associated with the key.\nFor strings this is the length of the string. For all the other types\nis the number of elements (just counting keys for hashes).\n\nIf the key pointer is NULL or the key is empty, zero is returned.\n\n<span id=\"RedisModule_DeleteKey\"></span>"
    },
    {
      "id": "redismodule-deletekey",
      "title": "`RedisModule_DeleteKey`",
      "role": "content",
      "text": "int RedisModule_DeleteKey(RedisModuleKey *key);\n\n**Available since:** 4.0.0\n\nIf the key is open for writing, remove it, and setup the key to\naccept new writes as an empty key (that will be created on demand).\nOn success `REDISMODULE_OK` is returned. If the key is not open for\nwriting `REDISMODULE_ERR` is returned.\n\n<span id=\"RedisModule_UnlinkKey\"></span>"
    },
    {
      "id": "redismodule-unlinkkey",
      "title": "`RedisModule_UnlinkKey`",
      "role": "content",
      "text": "int RedisModule_UnlinkKey(RedisModuleKey *key);\n\n**Available since:** 4.0.7\n\nIf the key is open for writing, unlink it (that is delete it in a\nnon-blocking way, not reclaiming memory immediately) and setup the key to\naccept new writes as an empty key (that will be created on demand).\nOn success `REDISMODULE_OK` is returned. If the key is not open for\nwriting `REDISMODULE_ERR` is returned.\n\n<span id=\"RedisModule_GetExpire\"></span>"
    },
    {
      "id": "redismodule-getexpire",
      "title": "`RedisModule_GetExpire`",
      "role": "content",
      "text": "mstime_t RedisModule_GetExpire(RedisModuleKey *key);\n\n**Available since:** 4.0.0\n\nReturn the key expire value, as milliseconds of remaining TTL.\nIf no TTL is associated with the key or if the key is empty,\n`REDISMODULE_NO_EXPIRE` is returned.\n\n<span id=\"RedisModule_SetExpire\"></span>"
    },
    {
      "id": "redismodule-setexpire",
      "title": "`RedisModule_SetExpire`",
      "role": "content",
      "text": "int RedisModule_SetExpire(RedisModuleKey *key, mstime_t expire);\n\n**Available since:** 4.0.0\n\nSet a new expire for the key. If the special expire\n`REDISMODULE_NO_EXPIRE` is set, the expire is cancelled if there was\none (the same as the PERSIST command).\n\nNote that the expire must be provided as a positive integer representing\nthe number of milliseconds of TTL the key should have.\n\nThe function returns `REDISMODULE_OK` on success or `REDISMODULE_ERR` if\nthe key was not open for writing or is an empty key.\n\n<span id=\"RedisModule_GetAbsExpire\"></span>"
    },
    {
      "id": "redismodule-getabsexpire",
      "title": "`RedisModule_GetAbsExpire`",
      "role": "content",
      "text": "mstime_t RedisModule_GetAbsExpire(RedisModuleKey *key);\n\n**Available since:** 6.2.2\n\nReturn the key expire value, as absolute Unix timestamp.\nIf no TTL is associated with the key or if the key is empty,\n`REDISMODULE_NO_EXPIRE` is returned.\n\n<span id=\"RedisModule_SetAbsExpire\"></span>"
    },
    {
      "id": "redismodule-setabsexpire",
      "title": "`RedisModule_SetAbsExpire`",
      "role": "content",
      "text": "int RedisModule_SetAbsExpire(RedisModuleKey *key, mstime_t expire);\n\n**Available since:** 6.2.2\n\nSet a new expire for the key. If the special expire\n`REDISMODULE_NO_EXPIRE` is set, the expire is cancelled if there was\none (the same as the PERSIST command).\n\nNote that the expire must be provided as a positive integer representing\nthe absolute Unix timestamp the key should have.\n\nThe function returns `REDISMODULE_OK` on success or `REDISMODULE_ERR` if\nthe key was not open for writing or is an empty key.\n\n<span id=\"RedisModule_CreateKeyMetaClass\"></span>"
    },
    {
      "id": "redismodule-createkeymetaclass",
      "title": "`RedisModule_CreateKeyMetaClass`",
      "role": "content",
      "text": "RedisModuleKeyMetaClassId RedisModule_CreateKeyMetaClass(RedisModuleCtx *ctx,;\n\n**Available since:** 8.6.0\n\nRegister a new key metadata class exported by the module.\n\nKey metadata allows modules to attach up to 8 bytes of metadata to any Redis key,\nregardless of the key's type. This metadata persists across key operations like\nCOPY, RENAME, MOVE, and can be saved/loaded from RDB files.\n\nThe parameters are the following:\n\n* **metaname**: A 9 characters metadata class name that MUST be unique in the Redis\n  Modules ecosystem. Use the charset A-Z a-z 0-9, plus the two \"-_\" characters.\n  A good idea is to use, for example `<metaname>-<vendor>`. For example\n  \"idx-RediSearch\" may mean \"Index metadata by RediSearch module\". To use both\n  lower case and upper case letters helps in order to prevent collisions.\n\n* **metaver**: Encoding version, which is the version of the serialization\n  that a module used in order to persist metadata. As long as the \"metaname\"\n  matches, the RDB loading will be dispatched to the metadata class callbacks\n  whatever 'metaver' is used, however the module can understand if\n  the encoding it must load is of an older version of the module.\n  For example the module \"idx-RediSearch\" initially used metaver=0. Later\n  after an upgrade, it started to serialize metadata in a different format\n  and to register the class with metaver=1. However this module may\n  still load old data produced by an older version if the `rdb_load`\n  callback is able to check the metaver value and act accordingly.\n  The metaver must be a positive value between 0 and 1023.\n\n* **confPtr** is a pointer to a `RedisModuleKeyMetaClassConfig` structure\n  that should be populated with the configuration and callbacks, like in\n  the following example:\n\n        RedisModuleKeyMetaClassConfig config = {\n            .version = REDISMODULE_KEY_META_VERSION,\n            .flags = 1 << REDISMODULE_META_ALLOW_IGNORE,\n            .reset_value = 0,\n            .copy = myMeta_CopyCallback,\n            .rename = myMeta_RenameCallback,\n            .move = myMeta_MoveCallback,\n            .unlink = myMeta_UnlinkCallback,\n            .free = myMeta_FreeCallback,\n            .rdb_load = myMeta_RDBLoadCallback,\n            .rdb_save = myMeta_RDBSaveCallback,\n            .aof_rewrite = myMeta_AOFRewriteCallback,\n            .defrag = myMeta_DefragCallback,\n            .mem_usage = myMeta_MemUsageCallback,\n            .free_effort = myMeta_FreeEffortCallback\n        }\n\n  Redis does NOT take ownership of the config structure itself. The `confPtr` \n  parameter only needs to remain valid during the [`RedisModule_CreateKeyMetaClass()`](#RedisModule_CreateKeyMetaClass) call \n  and can be freed immediately after.\n\n* **version**: Module must set it to `REDISMODULE_KEY_META_VERSION`. This field is\n  bumped when new fields are added; Redis keeps backward compatibility in\n  [`RedisModule_CreateKeyMetaClass()`](#RedisModule_CreateKeyMetaClass).\n\n* **flags**: Currently supports `REDISMODULE_META_ALLOW_IGNORE` (value 0).\n  When set, metadata will be silently ignored during RDB load if the module\n  is not available or if `rdb_load` callback is NULL. Otherwise, RDB loading\n  will fail if metadata is encountered but cannot be loaded.\n\n* **reset_value**: The value to which metadata should be reset when it is being\n  \"removed\" from a key. Typically 0, but can be any 8-byte value. This is\n  especially relevant when metadata is a pointer/handler to external resources.\n\n  IMPORTANT GUARANTEE: Redis only invokes callbacks when meta != `reset_value`.\n\n* **copy**: A callback function pointer for COPY command (optional).\n  - Return 1 to attach `meta` to the new key, or 0 to skip attaching metadata.\n  - If NULL, metadata is ignored during copy.\n  - The `meta` value may be modified in-place to produce a different value\n    for the new key.\n\n* **rename**: A callback function pointer for RENAME command (optional).\n  - If NULL, then metadata is kept during rename.\n  - The `meta` value may be modified in-place to produce a different value\n    for the new key.\n\n* **move**: A callback function pointer for MOVE command (optional).\n  - Return 1 to keep metadata, 0 to drop.\n  - If NULL, then metadata is kept during move.\n  - The `meta` value may be modified in-place to produce a different value\n    for the new key.\n\n* **unlink**: A callback function pointer for unlink operations (optional).\n  - If not provided, then metadata is ignored during unlink.\n  - Indication that key may soon be freed by background thread.\n  - Pointer to meta is provided for modification. If the metadata holds a pointer\n    or handle to resources and you free them here, you should set `*meta=reset_value`\n    to prevent the free callback from being invoked (Redis skips callbacks when\n    meta == reset_value, see reset_value documentation above).\n\n* **free**: A callback function pointer for cleanup (optional).\n  Invoked when a key with this metadata is deleted/overwritten/expired,\n  or when Redis needs to release per-key metadata during lifecycle operations.\n  The module should free any external allocation referenced by `meta`\n  if it uses the 8 bytes as a handle/pointer.\n  This callback may run in a background thread and is not protected by GIL.\n  It also might be called during RDB loading if the load fails after some\n  metadata has been successfully loaded. In this case, keyname will be NULL\n  since the key hasn't been created yet.\n\n* **rdb_load**: A callback function pointer for RDB loading (optional).\n  - Called during RDB loading when metadata for this class is encountered.\n  - Behavior when NULL:\n    > If rdb_load is NULL AND REDISMODULE_META_ALLOW_IGNORE flag is set,\n      the metadata will be silently ignored during RDB load.\n    > If rdb_load is NULL AND the flag is NOT set, RDB loading will fail\n      if metadata for this class is encountered.\n  - Behavior when class is not registered:\n    > If the class was saved with REDISMODULE_META_ALLOW_IGNORE flag but\n      is not registered at load time, the metadata will be silently ignored.\n    > Otherwise, RDB loading will fail.\n  - Callback responsibilities:\n    > Read custom serialized data from `rdb` using RedisModule_Load*() APIs\n    > Deserialize and reconstruct the 8-byte metadata value\n    > Write the final 8-byte value into `*meta`\n    > Return appropriate status code (see below)\n    > Database ID can be derived from `rdb` if needed. The associated key\n      will be loaded immediately after this callback returns.\n  - Parameters:\n    > rdb: RDB I/O context (use RedisModule_Load*() functions to read data)\n    > meta: Pointer to 8-byte metadata slot (write your deserialized value here)\n    > encver: Encoding version (the metadata class version at save time)\n  - Return values:\n    > 1: Attach value `*meta` to the key (success)\n    > 0: Ignore/skip metadata (don't attach, but continue loading - not an error)\n    > -1: Error - abort RDB load (e.g., invalid data, version incompatibility)\n           Module MUST clean up any allocated metadata before returning -1.\n\n* **rdb_save**: A callback function pointer for RDB saving (optional).\n  - If set to NULL, Redis will not save metadata to RDB.\n  - Callback should write data using RDB assisting functions: `RedisModule_Save*()`.\n\n* **aof_rewrite**: A callback function pointer for AOF rewrite (optional).\n  Called during AOF rewrite to emit commands that reconstruct the metadata.\n  IMPORTANT: For AOF/RDB persistence to work correctly, metadata classes must be\n  registered in `RedisModule_OnLoad()` so they are available when loading persisted\n  data on server startup.\n\n* **defrag**: A callback function pointer for active defragmentation (optional).\n  If the metadata contains pointers, this callback should defragment them.\n\n* **mem_usage**: A callback function pointer for MEMORY USAGE command (optional).\n  Should return the memory used by the metadata in bytes.\n\n* **free_effort**: A callback function pointer for lazy free (optional).\n  Should return the complexity of freeing the metadata to determine if\n  lazy free should be used.\n\nNote: the metadata class name \"AAAAAAAAA\" is reserved and produces an error.\n\nIf [`RedisModule_CreateKeyMetaClass()`](#RedisModule_CreateKeyMetaClass) is called outside of `RedisModule_OnLoad()` function,\nthere is already a metadata class registered with the same name,\nor if the metadata class name or metaver is invalid, a negative value is returned.\nOtherwise the new metadata class is registered into Redis, and a reference of\ntype `RedisModuleKeyMetaClassId` is returned: the caller of the function should store\nthis reference into a global variable to make future use of it in the\nmodules metadata API, since a single module may register multiple metadata classes.\nExample code fragment:\n\n     static RedisModuleKeyMetaClassId IndexMetaClass;\n\n     int RedisModule_OnLoad(RedisModuleCtx *ctx) {\n         // some code here ...\n         IndexMetaClass = RedisModule_CreateKeyMetaClass(...);\n     }\n\n<span id=\"RedisModule_ReleaseKeyMetaClass\"></span>"
    },
    {
      "id": "redismodule-releasekeymetaclass",
      "title": "`RedisModule_ReleaseKeyMetaClass`",
      "role": "content",
      "text": "int RedisModule_ReleaseKeyMetaClass(RedisModuleKeyMetaClassId id);\n\n**Available since:** 8.6.0\n\nRelease a class by its ID. Returns 1 on success, 0 on failure.\n\n<span id=\"RedisModule_SetKeyMeta\"></span>"
    },
    {
      "id": "redismodule-setkeymeta",
      "title": "`RedisModule_SetKeyMeta`",
      "role": "content",
      "text": "int RedisModule_SetKeyMeta(RedisModuleKeyMetaClassId id,\n                               RedisModuleKey *key,\n                               uint64_t metadata);\n\n**Available since:** 8.6.0\n\nSet metadata of class id on an opened key. If metadata is already attached,\nit will be overwritten. The caller is responsible for retrieving and freeing\nany existing pointer-based metadata before setting a new value.\n\n<span id=\"RedisModule_GetKeyMeta\"></span>"
    },
    {
      "id": "redismodule-getkeymeta",
      "title": "`RedisModule_GetKeyMeta`",
      "role": "content",
      "text": "int RedisModule_GetKeyMeta(RedisModuleKeyMetaClassId id,\n                               RedisModuleKey *key,\n                               uint64_t *metadata);\n\n**Available since:** 8.6.0\n\nGet metadata of class id from an opened key.\n\n<span id=\"RedisModule_ResetDataset\"></span>"
    },
    {
      "id": "redismodule-resetdataset",
      "title": "`RedisModule_ResetDataset`",
      "role": "content",
      "text": "void RedisModule_ResetDataset(int restart_aof, int async);\n\n**Available since:** 6.0.0\n\nPerforms similar operation to FLUSHALL, and optionally start a new AOF file (if enabled)\nIf `restart_aof` is true, you must make sure the command that triggered this call is not\npropagated to the AOF file.\nWhen async is set to true, db contents will be freed by a background thread.\n\n<span id=\"RedisModule_DbSize\"></span>"
    },
    {
      "id": "redismodule-dbsize",
      "title": "`RedisModule_DbSize`",
      "role": "content",
      "text": "unsigned long long RedisModule_DbSize(RedisModuleCtx *ctx);\n\n**Available since:** 6.0.0\n\nReturns the number of keys in the current db.\n\n<span id=\"RedisModule_RandomKey\"></span>"
    },
    {
      "id": "redismodule-randomkey",
      "title": "`RedisModule_RandomKey`",
      "role": "content",
      "text": "RedisModuleString *RedisModule_RandomKey(RedisModuleCtx *ctx);\n\n**Available since:** 6.0.0\n\nReturns a name of a random key, or NULL if current db is empty.\n\n<span id=\"RedisModule_GetKeyNameFromOptCtx\"></span>"
    },
    {
      "id": "redismodule-getkeynamefromoptctx",
      "title": "`RedisModule_GetKeyNameFromOptCtx`",
      "role": "content",
      "text": "const RedisModuleString *RedisModule_GetKeyNameFromOptCtx(RedisModuleKeyOptCtx *ctx);\n\n**Available since:** 7.0.0\n\nReturns the name of the key currently being processed.\n\n<span id=\"RedisModule_GetToKeyNameFromOptCtx\"></span>"
    },
    {
      "id": "redismodule-gettokeynamefromoptctx",
      "title": "`RedisModule_GetToKeyNameFromOptCtx`",
      "role": "content",
      "text": "const RedisModuleString *RedisModule_GetToKeyNameFromOptCtx(RedisModuleKeyOptCtx *ctx);\n\n**Available since:** 7.0.0\n\nReturns the name of the target key currently being processed.\n\n<span id=\"RedisModule_GetDbIdFromOptCtx\"></span>"
    },
    {
      "id": "redismodule-getdbidfromoptctx",
      "title": "`RedisModule_GetDbIdFromOptCtx`",
      "role": "content",
      "text": "int RedisModule_GetDbIdFromOptCtx(RedisModuleKeyOptCtx *ctx);\n\n**Available since:** 7.0.0\n\nReturns the dbid currently being processed.\n\n<span id=\"RedisModule_GetToDbIdFromOptCtx\"></span>"
    },
    {
      "id": "redismodule-gettodbidfromoptctx",
      "title": "`RedisModule_GetToDbIdFromOptCtx`",
      "role": "content",
      "text": "int RedisModule_GetToDbIdFromOptCtx(RedisModuleKeyOptCtx *ctx);\n\n**Available since:** 7.0.0\n\nReturns the target dbid currently being processed.\n\n<span id=\"section-key-api-for-string-type\"></span>"
    },
    {
      "id": "key-api-for-string-type",
      "title": "Key API for String type",
      "role": "content",
      "text": "See also [`RedisModule_ValueLength()`](#RedisModule_ValueLength), which returns the length of a string.\n\n<span id=\"RedisModule_StringSet\"></span>"
    },
    {
      "id": "redismodule-stringset",
      "title": "`RedisModule_StringSet`",
      "role": "content",
      "text": "int RedisModule_StringSet(RedisModuleKey *key, RedisModuleString *str);\n\n**Available since:** 4.0.0\n\nIf the key is open for writing, set the specified string 'str' as the\nvalue of the key, deleting the old value if any.\nOn success `REDISMODULE_OK` is returned. If the key is not open for\nwriting or there is an active iterator, `REDISMODULE_ERR` is returned.\n\n<span id=\"RedisModule_StringDMA\"></span>"
    },
    {
      "id": "redismodule-stringdma",
      "title": "`RedisModule_StringDMA`",
      "role": "content",
      "text": "char *RedisModule_StringDMA(RedisModuleKey *key, size_t *len, int mode);\n\n**Available since:** 4.0.0\n\nPrepare the key associated string value for DMA access, and returns\na pointer and size (by reference), that the user can use to read or\nmodify the string in-place accessing it directly via pointer.\n\nThe 'mode' is composed by bitwise OR-ing the following flags:\n\n    REDISMODULE_READ -- Read access\n    REDISMODULE_WRITE -- Write access\n\nIf the DMA is not requested for writing, the pointer returned should\nonly be accessed in a read-only fashion.\n\nOn error (wrong type) NULL is returned.\n\nDMA access rules:\n\n1. No other key writing function should be called since the moment\nthe pointer is obtained, for all the time we want to use DMA access\nto read or modify the string.\n\n2. Each time [`RedisModule_StringTruncate()`](#RedisModule_StringTruncate) is called, to continue with the DMA\naccess, [`RedisModule_StringDMA()`](#RedisModule_StringDMA) should be called again to re-obtain\na new pointer and length.\n\n3. If the returned pointer is not NULL, but the length is zero, no\nbyte can be touched (the string is empty, or the key itself is empty)\nso a [`RedisModule_StringTruncate()`](#RedisModule_StringTruncate) call should be used if there is to enlarge\nthe string, and later call StringDMA() again to get the pointer.\n\n<span id=\"RedisModule_StringTruncate\"></span>"
    },
    {
      "id": "redismodule-stringtruncate",
      "title": "`RedisModule_StringTruncate`",
      "role": "content",
      "text": "int RedisModule_StringTruncate(RedisModuleKey *key, size_t newlen);\n\n**Available since:** 4.0.0\n\nIf the key is open for writing and is of string type, resize it, padding\nwith zero bytes if the new length is greater than the old one.\n\nAfter this call, [`RedisModule_StringDMA()`](#RedisModule_StringDMA) must be called again to continue\nDMA access with the new pointer.\n\nThe function returns `REDISMODULE_OK` on success, and `REDISMODULE_ERR` on\nerror, that is, the key is not open for writing, is not a string\nor resizing for more than 512 MB is requested.\n\nIf the key is empty, a string key is created with the new string value\nunless the new length value requested is zero.\n\n<span id=\"section-key-api-for-list-type\"></span>"
    },
    {
      "id": "key-api-for-list-type",
      "title": "Key API for List type",
      "role": "content",
      "text": "Many of the list functions access elements by index. Since a list is in\nessence a doubly-linked list, accessing elements by index is generally an\nO(N) operation. However, if elements are accessed sequentially or with\nindices close together, the functions are optimized to seek the index from\nthe previous index, rather than seeking from the ends of the list.\n\nThis enables iteration to be done efficiently using a simple for loop:\n\n    long n = RedisModule_ValueLength(key);\n    for (long i = 0; i < n; i++) {\n        RedisModuleString *elem = RedisModule_ListGet(key, i);\n        // Do stuff...\n    }\n\nNote that after modifying a list using [`RedisModule_ListPop`](#RedisModule_ListPop), [`RedisModule_ListSet`](#RedisModule_ListSet) or\n[`RedisModule_ListInsert`](#RedisModule_ListInsert), the internal iterator is invalidated so the next operation\nwill require a linear seek.\n\nModifying a list in any another way, for example using [`RedisModule_Call()`](#RedisModule_Call), while a key\nis open will confuse the internal iterator and may cause trouble if the key\nis used after such modifications. The key must be reopened in this case.\n\nSee also [`RedisModule_ValueLength()`](#RedisModule_ValueLength), which returns the length of a list.\n\n<span id=\"RedisModule_ListPush\"></span>"
    },
    {
      "id": "redismodule-listpush",
      "title": "`RedisModule_ListPush`",
      "role": "content",
      "text": "int RedisModule_ListPush(RedisModuleKey *key,\n                             int where,\n                             RedisModuleString *ele);\n\n**Available since:** 4.0.0\n\nPush an element into a list, on head or tail depending on 'where' argument\n(`REDISMODULE_LIST_HEAD` or `REDISMODULE_LIST_TAIL`). If the key refers to an\nempty key opened for writing, the key is created. On success, `REDISMODULE_OK`\nis returned. On failure, `REDISMODULE_ERR` is returned and `errno` is set as\nfollows:\n\n- EINVAL if key or ele is NULL.\n- ENOTSUP if the key is of another type than list.\n- EBADF if the key is not opened for writing.\n\nNote: Before Redis 7.0, `errno` was not set by this function.\n\n<span id=\"RedisModule_ListPop\"></span>"
    },
    {
      "id": "redismodule-listpop",
      "title": "`RedisModule_ListPop`",
      "role": "content",
      "text": "RedisModuleString *RedisModule_ListPop(RedisModuleKey *key, int where);\n\n**Available since:** 4.0.0\n\nPop an element from the list, and returns it as a module string object\nthat the user should be free with [`RedisModule_FreeString()`](#RedisModule_FreeString) or by enabling\nautomatic memory. The `where` argument specifies if the element should be\npopped from the beginning or the end of the list (`REDISMODULE_LIST_HEAD` or\n`REDISMODULE_LIST_TAIL`). On failure, the command returns NULL and sets\n`errno` as follows:\n\n- EINVAL if key is NULL.\n- ENOTSUP if the key is empty or of another type than list.\n- EBADF if the key is not opened for writing.\n\nNote: Before Redis 7.0, `errno` was not set by this function.\n\n<span id=\"RedisModule_ListGet\"></span>"
    },
    {
      "id": "redismodule-listget",
      "title": "`RedisModule_ListGet`",
      "role": "content",
      "text": "RedisModuleString *RedisModule_ListGet(RedisModuleKey *key, long index);\n\n**Available since:** 7.0.0\n\nReturns the element at index `index` in the list stored at `key`, like the\nLINDEX command. The element should be free'd using [`RedisModule_FreeString()`](#RedisModule_FreeString) or using\nautomatic memory management.\n\nThe index is zero-based, so 0 means the first element, 1 the second element\nand so on. Negative indices can be used to designate elements starting at the\ntail of the list. Here, -1 means the last element, -2 means the penultimate\nand so forth.\n\nWhen no value is found at the given key and index, NULL is returned and\n`errno` is set as follows:\n\n- EINVAL if key is NULL.\n- ENOTSUP if the key is not a list.\n- EBADF if the key is not opened for reading.\n- EDOM if the index is not a valid index in the list.\n\n<span id=\"RedisModule_ListSet\"></span>"
    },
    {
      "id": "redismodule-listset",
      "title": "`RedisModule_ListSet`",
      "role": "content",
      "text": "int RedisModule_ListSet(RedisModuleKey *key,\n                            long index,\n                            RedisModuleString *value);\n\n**Available since:** 7.0.0\n\nReplaces the element at index `index` in the list stored at `key`.\n\nThe index is zero-based, so 0 means the first element, 1 the second element\nand so on. Negative indices can be used to designate elements starting at the\ntail of the list. Here, -1 means the last element, -2 means the penultimate\nand so forth.\n\nOn success, `REDISMODULE_OK` is returned. On failure, `REDISMODULE_ERR` is\nreturned and `errno` is set as follows:\n\n- EINVAL if key or value is NULL.\n- ENOTSUP if the key is not a list.\n- EBADF if the key is not opened for writing.\n- EDOM if the index is not a valid index in the list.\n\n<span id=\"RedisModule_ListInsert\"></span>"
    },
    {
      "id": "redismodule-listinsert",
      "title": "`RedisModule_ListInsert`",
      "role": "content",
      "text": "int RedisModule_ListInsert(RedisModuleKey *key,\n                               long index,\n                               RedisModuleString *value);\n\n**Available since:** 7.0.0\n\nInserts an element at the given index.\n\nThe index is zero-based, so 0 means the first element, 1 the second element\nand so on. Negative indices can be used to designate elements starting at the\ntail of the list. Here, -1 means the last element, -2 means the penultimate\nand so forth. The index is the element's index after inserting it.\n\nOn success, `REDISMODULE_OK` is returned. On failure, `REDISMODULE_ERR` is\nreturned and `errno` is set as follows:\n\n- EINVAL if key or value is NULL.\n- ENOTSUP if the key of another type than list.\n- EBADF if the key is not opened for writing.\n- EDOM if the index is not a valid index in the list.\n\n<span id=\"RedisModule_ListDelete\"></span>"
    },
    {
      "id": "redismodule-listdelete",
      "title": "`RedisModule_ListDelete`",
      "role": "content",
      "text": "int RedisModule_ListDelete(RedisModuleKey *key, long index);\n\n**Available since:** 7.0.0\n\nRemoves an element at the given index. The index is 0-based. A negative index\ncan also be used, counting from the end of the list.\n\nOn success, `REDISMODULE_OK` is returned. On failure, `REDISMODULE_ERR` is\nreturned and `errno` is set as follows:\n\n- EINVAL if key or value is NULL.\n- ENOTSUP if the key is not a list.\n- EBADF if the key is not opened for writing.\n- EDOM if the index is not a valid index in the list.\n\n<span id=\"section-key-api-for-sorted-set-type\"></span>"
    },
    {
      "id": "key-api-for-sorted-set-type",
      "title": "Key API for Sorted Set type",
      "role": "content",
      "text": "See also [`RedisModule_ValueLength()`](#RedisModule_ValueLength), which returns the length of a sorted set.\n\n<span id=\"RedisModule_ZsetAdd\"></span>"
    },
    {
      "id": "redismodule-zsetadd",
      "title": "`RedisModule_ZsetAdd`",
      "role": "content",
      "text": "int RedisModule_ZsetAdd(RedisModuleKey *key,\n                            double score,\n                            RedisModuleString *ele,\n                            int *flagsptr);\n\n**Available since:** 4.0.0\n\nAdd a new element into a sorted set, with the specified 'score'.\nIf the element already exists, the score is updated.\n\nA new sorted set is created at value if the key is an empty open key\nsetup for writing.\n\nAdditional flags can be passed to the function via a pointer, the flags\nare both used to receive input and to communicate state when the function\nreturns. 'flagsptr' can be NULL if no special flags are used.\n\nThe input flags are:\n\n    REDISMODULE_ZADD_XX: Element must already exist. Do nothing otherwise.\n    REDISMODULE_ZADD_NX: Element must not exist. Do nothing otherwise.\n    REDISMODULE_ZADD_GT: If element exists, new score must be greater than the current score. \n                         Do nothing otherwise. Can optionally be combined with XX.\n    REDISMODULE_ZADD_LT: If element exists, new score must be less than the current score.\n                         Do nothing otherwise. Can optionally be combined with XX.\n\nThe output flags are:\n\n    REDISMODULE_ZADD_ADDED: The new element was added to the sorted set.\n    REDISMODULE_ZADD_UPDATED: The score of the element was updated.\n    REDISMODULE_ZADD_NOP: No operation was performed because XX or NX flags.\n\nOn success the function returns `REDISMODULE_OK`. On the following errors\n`REDISMODULE_ERR` is returned:\n\n* The key was not opened for writing.\n* The key is of the wrong type.\n* 'score' double value is not a number (NaN).\n\n<span id=\"RedisModule_ZsetIncrby\"></span>"
    },
    {
      "id": "redismodule-zsetincrby",
      "title": "`RedisModule_ZsetIncrby`",
      "role": "content",
      "text": "int RedisModule_ZsetIncrby(RedisModuleKey *key,\n                               double score,\n                               RedisModuleString *ele,\n                               int *flagsptr,\n                               double *newscore);\n\n**Available since:** 4.0.0\n\nThis function works exactly like [`RedisModule_ZsetAdd()`](#RedisModule_ZsetAdd), but instead of setting\na new score, the score of the existing element is incremented, or if the\nelement does not already exist, it is added assuming the old score was\nzero.\n\nThe input and output flags, and the return value, have the same exact\nmeaning, with the only difference that this function will return\n`REDISMODULE_ERR` even when 'score' is a valid double number, but adding it\nto the existing score results into a NaN (not a number) condition.\n\nThis function has an additional field 'newscore', if not NULL is filled\nwith the new score of the element after the increment, if no error\nis returned.\n\n<span id=\"RedisModule_ZsetRem\"></span>"
    },
    {
      "id": "redismodule-zsetrem",
      "title": "`RedisModule_ZsetRem`",
      "role": "content",
      "text": "int RedisModule_ZsetRem(RedisModuleKey *key,\n                            RedisModuleString *ele,\n                            int *deleted);\n\n**Available since:** 4.0.0\n\nRemove the specified element from the sorted set.\nThe function returns `REDISMODULE_OK` on success, and `REDISMODULE_ERR`\non one of the following conditions:\n\n* The key was not opened for writing.\n* The key is of the wrong type.\n\nThe return value does NOT indicate the fact the element was really\nremoved (since it existed) or not, just if the function was executed\nwith success.\n\nIn order to know if the element was removed, the additional argument\n'deleted' must be passed, that populates the integer by reference\nsetting it to 1 or 0 depending on the outcome of the operation.\nThe 'deleted' argument can be NULL if the caller is not interested\nto know if the element was really removed.\n\nEmpty keys will be handled correctly by doing nothing.\n\n<span id=\"RedisModule_ZsetScore\"></span>"
    },
    {
      "id": "redismodule-zsetscore",
      "title": "`RedisModule_ZsetScore`",
      "role": "content",
      "text": "int RedisModule_ZsetScore(RedisModuleKey *key,\n                              RedisModuleString *ele,\n                              double *score);\n\n**Available since:** 4.0.0\n\nOn success retrieve the double score associated at the sorted set element\n'ele' and returns `REDISMODULE_OK`. Otherwise `REDISMODULE_ERR` is returned\nto signal one of the following conditions:\n\n* There is no such element 'ele' in the sorted set.\n* The key is not a sorted set.\n* The key is an open empty key.\n\n<span id=\"section-key-api-for-sorted-set-iterator\"></span>"
    },
    {
      "id": "key-api-for-sorted-set-iterator",
      "title": "Key API for Sorted Set iterator",
      "role": "content",
      "text": "<span id=\"RedisModule_ZsetRangeStop\"></span>"
    },
    {
      "id": "redismodule-zsetrangestop",
      "title": "`RedisModule_ZsetRangeStop`",
      "role": "content",
      "text": "void RedisModule_ZsetRangeStop(RedisModuleKey *key);\n\n**Available since:** 4.0.0\n\nStop a sorted set iteration.\n\n<span id=\"RedisModule_ZsetRangeEndReached\"></span>"
    },
    {
      "id": "redismodule-zsetrangeendreached",
      "title": "`RedisModule_ZsetRangeEndReached`",
      "role": "content",
      "text": "int RedisModule_ZsetRangeEndReached(RedisModuleKey *key);\n\n**Available since:** 4.0.0\n\nReturn the \"End of range\" flag value to signal the end of the iteration.\n\n<span id=\"RedisModule_ZsetFirstInScoreRange\"></span>"
    },
    {
      "id": "redismodule-zsetfirstinscorerange",
      "title": "`RedisModule_ZsetFirstInScoreRange`",
      "role": "content",
      "text": "int RedisModule_ZsetFirstInScoreRange(RedisModuleKey *key,\n                                          double min,\n                                          double max,\n                                          int minex,\n                                          int maxex);\n\n**Available since:** 4.0.0\n\nSetup a sorted set iterator seeking the first element in the specified\nrange. Returns `REDISMODULE_OK` if the iterator was correctly initialized\notherwise `REDISMODULE_ERR` is returned in the following conditions:\n\n1. The value stored at key is not a sorted set or the key is empty.\n\nThe range is specified according to the two double values 'min' and 'max'.\nBoth can be infinite using the following two macros:\n\n* `REDISMODULE_POSITIVE_INFINITE` for positive infinite value\n* `REDISMODULE_NEGATIVE_INFINITE` for negative infinite value\n\n'minex' and 'maxex' parameters, if true, respectively setup a range\nwhere the min and max value are exclusive (not included) instead of\ninclusive.\n\n<span id=\"RedisModule_ZsetLastInScoreRange\"></span>"
    },
    {
      "id": "redismodule-zsetlastinscorerange",
      "title": "`RedisModule_ZsetLastInScoreRange`",
      "role": "content",
      "text": "int RedisModule_ZsetLastInScoreRange(RedisModuleKey *key,\n                                         double min,\n                                         double max,\n                                         int minex,\n                                         int maxex);\n\n**Available since:** 4.0.0\n\nExactly like [`RedisModule_ZsetFirstInScoreRange()`](#RedisModule_ZsetFirstInScoreRange) but the last element of\nthe range is selected for the start of the iteration instead.\n\n<span id=\"RedisModule_ZsetFirstInLexRange\"></span>"
    },
    {
      "id": "redismodule-zsetfirstinlexrange",
      "title": "`RedisModule_ZsetFirstInLexRange`",
      "role": "content",
      "text": "int RedisModule_ZsetFirstInLexRange(RedisModuleKey *key,\n                                        RedisModuleString *min,\n                                        RedisModuleString *max);\n\n**Available since:** 4.0.0\n\nSetup a sorted set iterator seeking the first element in the specified\nlexicographical range. Returns `REDISMODULE_OK` if the iterator was correctly\ninitialized otherwise `REDISMODULE_ERR` is returned in the\nfollowing conditions:\n\n1. The value stored at key is not a sorted set or the key is empty.\n2. The lexicographical range 'min' and 'max' format is invalid.\n\n'min' and 'max' should be provided as two `RedisModuleString` objects\nin the same format as the parameters passed to the ZRANGEBYLEX command.\nThe function does not take ownership of the objects, so they can be released\nASAP after the iterator is setup.\n\n<span id=\"RedisModule_ZsetLastInLexRange\"></span>"
    },
    {
      "id": "redismodule-zsetlastinlexrange",
      "title": "`RedisModule_ZsetLastInLexRange`",
      "role": "content",
      "text": "int RedisModule_ZsetLastInLexRange(RedisModuleKey *key,\n                                       RedisModuleString *min,\n                                       RedisModuleString *max);\n\n**Available since:** 4.0.0\n\nExactly like [`RedisModule_ZsetFirstInLexRange()`](#RedisModule_ZsetFirstInLexRange) but the last element of\nthe range is selected for the start of the iteration instead.\n\n<span id=\"RedisModule_ZsetRangeCurrentElement\"></span>"
    },
    {
      "id": "redismodule-zsetrangecurrentelement",
      "title": "`RedisModule_ZsetRangeCurrentElement`",
      "role": "content",
      "text": "RedisModuleString *RedisModule_ZsetRangeCurrentElement(RedisModuleKey *key,\n                                                           double *score);\n\n**Available since:** 4.0.0\n\nReturn the current sorted set element of an active sorted set iterator\nor NULL if the range specified in the iterator does not include any\nelement.\n\n<span id=\"RedisModule_ZsetRangeNext\"></span>"
    },
    {
      "id": "redismodule-zsetrangenext",
      "title": "`RedisModule_ZsetRangeNext`",
      "role": "content",
      "text": "int RedisModule_ZsetRangeNext(RedisModuleKey *key);\n\n**Available since:** 4.0.0\n\nGo to the next element of the sorted set iterator. Returns 1 if there was\na next element, 0 if we are already at the latest element or the range\ndoes not include any item at all.\n\n<span id=\"RedisModule_ZsetRangePrev\"></span>"
    },
    {
      "id": "redismodule-zsetrangeprev",
      "title": "`RedisModule_ZsetRangePrev`",
      "role": "content",
      "text": "int RedisModule_ZsetRangePrev(RedisModuleKey *key);\n\n**Available since:** 4.0.0\n\nGo to the previous element of the sorted set iterator. Returns 1 if there was\na previous element, 0 if we are already at the first element or the range\ndoes not include any item at all.\n\n<span id=\"section-key-api-for-hash-type\"></span>"
    },
    {
      "id": "key-api-for-hash-type",
      "title": "Key API for Hash type",
      "role": "content",
      "text": "See also [`RedisModule_ValueLength()`](#RedisModule_ValueLength), which returns the number of fields in a hash.\n\n<span id=\"RedisModule_HashSet\"></span>"
    },
    {
      "id": "redismodule-hashset",
      "title": "`RedisModule_HashSet`",
      "role": "content",
      "text": "int RedisModule_HashSet(RedisModuleKey *key, int flags, ...);\n\n**Available since:** 4.0.0\n\nSet the field of the specified hash field to the specified value.\nIf the key is an empty key open for writing, it is created with an empty\nhash value, in order to set the specified field.\n\nThe function is variadic and the user must specify pairs of field\nnames and values, both as `RedisModuleString` pointers (unless the\nCFIELD option is set, see later). At the end of the field/value-ptr pairs,\nNULL must be specified as last argument to signal the end of the arguments\nin the variadic function.\n\nExample to set the hash argv[1] to the value argv[2]:\n\n     RedisModule_HashSet(key,REDISMODULE_HASH_NONE,argv[1],argv[2],NULL);\n\nThe function can also be used in order to delete fields (if they exist)\nby setting them to the specified value of `REDISMODULE_HASH_DELETE`:\n\n     RedisModule_HashSet(key,REDISMODULE_HASH_NONE,argv[1],\n                         REDISMODULE_HASH_DELETE,NULL);\n\nThe behavior of the command changes with the specified flags, that can be\nset to `REDISMODULE_HASH_NONE` if no special behavior is needed.\n\n    REDISMODULE_HASH_NX: The operation is performed only if the field was not\n                         already existing in the hash.\n    REDISMODULE_HASH_XX: The operation is performed only if the field was\n                         already existing, so that a new value could be\n                         associated to an existing filed, but no new fields\n                         are created.\n    REDISMODULE_HASH_CFIELDS: The field names passed are null terminated C\n                              strings instead of RedisModuleString objects.\n    REDISMODULE_HASH_COUNT_ALL: Include the number of inserted fields in the\n                                returned number, in addition to the number of\n                                updated and deleted fields. (Added in Redis\n                                6.2.)\n\nUnless NX is specified, the command overwrites the old field value with\nthe new one.\n\nWhen using `REDISMODULE_HASH_CFIELDS`, field names are reported using\nnormal C strings, so for example to delete the field \"foo\" the following\ncode can be used:\n\n     RedisModule_HashSet(key,REDISMODULE_HASH_CFIELDS,\"foo\",\n                         REDISMODULE_HASH_DELETE,NULL);\n\nReturn value:\n\nThe number of fields existing in the hash prior to the call, which have been\nupdated (its old value has been replaced by a new value) or deleted. If the\nflag `REDISMODULE_HASH_COUNT_ALL` is set, inserted fields not previously\nexisting in the hash are also counted.\n\nIf the return value is zero, `errno` is set (since Redis 6.2) as follows:\n\n- EINVAL if any unknown flags are set or if key is NULL.\n- ENOTSUP if the key is associated with a non Hash value.\n- EBADF if the key was not opened for writing.\n- ENOENT if no fields were counted as described under Return value above.\n  This is not actually an error. The return value can be zero if all fields\n  were just created and the `COUNT_ALL` flag was unset, or if changes were held\n  back due to the NX and XX flags.\n\nNOTICE: The return value semantics of this function are very different\nbetween Redis 6.2 and older versions. Modules that use it should determine\nthe Redis version and handle it accordingly.\n\n<span id=\"RedisModule_HashGet\"></span>"
    },
    {
      "id": "redismodule-hashget",
      "title": "`RedisModule_HashGet`",
      "role": "content",
      "text": "int RedisModule_HashGet(RedisModuleKey *key, int flags, ...);\n\n**Available since:** 4.0.0\n\nGet fields from a hash value. This function is called using a variable\nnumber of arguments, alternating a field name (as a `RedisModuleString`\npointer) with a pointer to a `RedisModuleString` pointer, that is set to the\nvalue of the field if the field exists, or NULL if the field does not exist.\nAt the end of the field/value-ptr pairs, NULL must be specified as last\nargument to signal the end of the arguments in the variadic function.\n\nThis is an example usage:\n\n     RedisModuleString *first, *second;\n     RedisModule_HashGet(mykey,REDISMODULE_HASH_NONE,argv[1],&first,\n                         argv[2],&second,NULL);\n\nAs with [`RedisModule_HashSet()`](#RedisModule_HashSet) the behavior of the command can be specified\npassing flags different than `REDISMODULE_HASH_NONE`:\n\n`REDISMODULE_HASH_CFIELDS`: field names as null terminated C strings.\n\n`REDISMODULE_HASH_EXISTS`: instead of setting the value of the field\nexpecting a `RedisModuleString` pointer to pointer, the function just\nreports if the field exists or not and expects an integer pointer\nas the second element of each pair.\n\n`REDISMODULE_HASH_EXPIRE_TIME`: retrieves the expiration time of a field in the hash.\nThe function expects a `mstime_t` pointer as the second element of each pair.\nIf the field does not exist or has no expiration, the value is set to \n`REDISMODULE_NO_EXPIRE`. This flag must not be used with `REDISMODULE_HASH_EXISTS`.\n\nExample of `REDISMODULE_HASH_CFIELDS`:\n\n     RedisModuleString *username, *hashedpass;\n     RedisModule_HashGet(mykey,REDISMODULE_HASH_CFIELDS,\"username\",&username,\"hp\",&hashedpass, NULL);\n\nExample of `REDISMODULE_HASH_EXISTS`:\n\n     int exists;\n     RedisModule_HashGet(mykey,REDISMODULE_HASH_EXISTS,\"username\",&exists,NULL);\n\nExample of `REDISMODULE_HASH_EXPIRE_TIME`:\n\n     mstime_t hpExpireTime; \n     RedisModule_HashGet(mykey,REDISMODULE_HASH_EXPIRE_TIME,\"hp\",&hpExpireTime,NULL);\n     \nThe function returns `REDISMODULE_OK` on success and `REDISMODULE_ERR` if\nthe key is not a hash value.\n\nMemory management:\n\nThe returned `RedisModuleString` objects should be released with\n[`RedisModule_FreeString()`](#RedisModule_FreeString), or by enabling automatic memory management.\n\n<span id=\"RedisModule_HashFieldMinExpire\"></span>"
    },
    {
      "id": "redismodule-hashfieldminexpire",
      "title": "`RedisModule_HashFieldMinExpire`",
      "role": "content",
      "text": "mstime_t RedisModule_HashFieldMinExpire(RedisModuleKey *key);\n\n**Available since:** 8.0.0\n\n\nRetrieves the minimum expiration time of fields in a hash.\n\nReturn:\n  - The minimum expiration time (in milliseconds) of the hash fields if at\n    least one field has an expiration set.\n  - `REDISMODULE_NO_EXPIRE` if no fields have an expiration set or if the key\n    is not a hash.\n\n<span id=\"section-key-api-for-stream-type\"></span>"
    },
    {
      "id": "key-api-for-stream-type",
      "title": "Key API for Stream type",
      "role": "content",
      "text": "For an introduction to streams, see [https://un5pn9hmggug.julianrbryant.com/docs/latest/develop/data-types/streams/](https://un5pn9hmggug.julianrbryant.com/docs/latest/develop/data-types/streams/).\n\nThe type `RedisModuleStreamID`, which is used in stream functions, is a struct\nwith two 64-bit fields and is defined as\n\n    typedef struct RedisModuleStreamID {\n        uint64_t ms;\n        uint64_t seq;\n    } RedisModuleStreamID;\n\nSee also [`RedisModule_ValueLength()`](#RedisModule_ValueLength), which returns the length of a stream, and the\nconversion functions [`RedisModule_StringToStreamID()`](#RedisModule_StringToStreamID) and [`RedisModule_CreateStringFromStreamID()`](#RedisModule_CreateStringFromStreamID).\n\n<span id=\"RedisModule_StreamAdd\"></span>"
    },
    {
      "id": "redismodule-streamadd",
      "title": "`RedisModule_StreamAdd`",
      "role": "content",
      "text": "int RedisModule_StreamAdd(RedisModuleKey *key,\n                              int flags,\n                              RedisModuleStreamID *id,\n                              RedisModuleString **argv,\n                              long numfields);\n\n**Available since:** 6.2.0\n\nAdds an entry to a stream. Like XADD without trimming.\n\n- `key`: The key where the stream is (or will be) stored\n- `flags`: A bit field of\n  - `REDISMODULE_STREAM_ADD_AUTOID`: Assign a stream ID automatically, like\n    `*` in the XADD command.\n- `id`: If the `AUTOID` flag is set, this is where the assigned ID is\n  returned. Can be NULL if `AUTOID` is set, if you don't care to receive the\n  ID. If `AUTOID` is not set, this is the requested ID.\n- `argv`: A pointer to an array of size `numfields * 2` containing the\n  fields and values.\n- `numfields`: The number of field-value pairs in `argv`.\n\nReturns `REDISMODULE_OK` if an entry has been added. On failure,\n`REDISMODULE_ERR` is returned and `errno` is set as follows:\n\n- EINVAL if called with invalid arguments\n- ENOTSUP if the key refers to a value of a type other than stream\n- EBADF if the key was not opened for writing\n- EDOM if the given ID was 0-0 or not greater than all other IDs in the\n  stream (only if the AUTOID flag is unset)\n- EFBIG if the stream has reached the last possible ID\n- ERANGE if the elements are too large to be stored.\n\n<span id=\"RedisModule_StreamDelete\"></span>"
    },
    {
      "id": "redismodule-streamdelete",
      "title": "`RedisModule_StreamDelete`",
      "role": "content",
      "text": "int RedisModule_StreamDelete(RedisModuleKey *key, RedisModuleStreamID *id);\n\n**Available since:** 6.2.0\n\nDeletes an entry from a stream.\n\n- `key`: A key opened for writing, with no stream iterator started.\n- `id`: The stream ID of the entry to delete.\n\nReturns `REDISMODULE_OK` on success. On failure, `REDISMODULE_ERR` is returned\nand `errno` is set as follows:\n\n- EINVAL if called with invalid arguments\n- ENOTSUP if the key refers to a value of a type other than stream or if the\n  key is empty\n- EBADF if the key was not opened for writing or if a stream iterator is\n  associated with the key\n- ENOENT if no entry with the given stream ID exists\n\nSee also [`RedisModule_StreamIteratorDelete()`](#RedisModule_StreamIteratorDelete) for deleting the current entry while\niterating using a stream iterator.\n\n<span id=\"RedisModule_StreamIteratorStart\"></span>"
    },
    {
      "id": "redismodule-streamiteratorstart",
      "title": "`RedisModule_StreamIteratorStart`",
      "role": "content",
      "text": "int RedisModule_StreamIteratorStart(RedisModuleKey *key,\n                                        int flags,\n                                        RedisModuleStreamID *start,\n                                        RedisModuleStreamID *end);\n\n**Available since:** 6.2.0\n\nSets up a stream iterator.\n\n- `key`: The stream key opened for reading using [`RedisModule_OpenKey()`](#RedisModule_OpenKey).\n- `flags`:\n  - `REDISMODULE_STREAM_ITERATOR_EXCLUSIVE`: Don't include `start` and `end`\n    in the iterated range.\n  - `REDISMODULE_STREAM_ITERATOR_REVERSE`: Iterate in reverse order, starting\n    from the `end` of the range.\n- `start`: The lower bound of the range. Use NULL for the beginning of the\n  stream.\n- `end`: The upper bound of the range. Use NULL for the end of the stream.\n\nReturns `REDISMODULE_OK` on success. On failure, `REDISMODULE_ERR` is returned\nand `errno` is set as follows:\n\n- EINVAL if called with invalid arguments\n- ENOTSUP if the key refers to a value of a type other than stream or if the\n  key is empty\n- EBADF if the key was not opened for writing or if a stream iterator is\n  already associated with the key\n- EDOM if `start` or `end` is outside the valid range\n\nReturns `REDISMODULE_OK` on success and `REDISMODULE_ERR` if the key doesn't\nrefer to a stream or if invalid arguments were given.\n\nThe stream IDs are retrieved using [`RedisModule_StreamIteratorNextID()`](#RedisModule_StreamIteratorNextID) and\nfor each stream ID, the fields and values are retrieved using\n[`RedisModule_StreamIteratorNextField()`](#RedisModule_StreamIteratorNextField). The iterator is freed by calling\n[`RedisModule_StreamIteratorStop()`](#RedisModule_StreamIteratorStop).\n\nExample (error handling omitted):\n\n    RedisModule_StreamIteratorStart(key, 0, startid_ptr, endid_ptr);\n    RedisModuleStreamID id;\n    long numfields;\n    while (RedisModule_StreamIteratorNextID(key, &id, &numfields) ==\n           REDISMODULE_OK) {\n        RedisModuleString *field, *value;\n        while (RedisModule_StreamIteratorNextField(key, &field, &value) ==\n               REDISMODULE_OK) {\n            //\n            // ... Do stuff ...\n            //\n            RedisModule_FreeString(ctx, field);\n            RedisModule_FreeString(ctx, value);\n        }\n    }\n    RedisModule_StreamIteratorStop(key);\n\n<span id=\"RedisModule_StreamIteratorStop\"></span>"
    },
    {
      "id": "redismodule-streamiteratorstop",
      "title": "`RedisModule_StreamIteratorStop`",
      "role": "content",
      "text": "int RedisModule_StreamIteratorStop(RedisModuleKey *key);\n\n**Available since:** 6.2.0\n\nStops a stream iterator created using [`RedisModule_StreamIteratorStart()`](#RedisModule_StreamIteratorStart) and\nreclaims its memory.\n\nReturns `REDISMODULE_OK` on success. On failure, `REDISMODULE_ERR` is returned\nand `errno` is set as follows:\n\n- EINVAL if called with a NULL key\n- ENOTSUP if the key refers to a value of a type other than stream or if the\n  key is empty\n- EBADF if the key was not opened for writing or if no stream iterator is\n  associated with the key\n\n<span id=\"RedisModule_StreamIteratorNextID\"></span>"
    },
    {
      "id": "redismodule-streamiteratornextid",
      "title": "`RedisModule_StreamIteratorNextID`",
      "role": "content",
      "text": "int RedisModule_StreamIteratorNextID(RedisModuleKey *key,\n                                         RedisModuleStreamID *id,\n                                         long *numfields);\n\n**Available since:** 6.2.0\n\nFinds the next stream entry and returns its stream ID and the number of\nfields.\n\n- `key`: Key for which a stream iterator has been started using\n  [`RedisModule_StreamIteratorStart()`](#RedisModule_StreamIteratorStart).\n- `id`: The stream ID returned. NULL if you don't care.\n- `numfields`: The number of fields in the found stream entry. NULL if you\n  don't care.\n\nReturns `REDISMODULE_OK` and sets `*id` and `*numfields` if an entry was found.\nOn failure, `REDISMODULE_ERR` is returned and `errno` is set as follows:\n\n- EINVAL if called with a NULL key\n- ENOTSUP if the key refers to a value of a type other than stream or if the\n  key is empty\n- EBADF if no stream iterator is associated with the key\n- ENOENT if there are no more entries in the range of the iterator\n\nIn practice, if [`RedisModule_StreamIteratorNextID()`](#RedisModule_StreamIteratorNextID) is called after a successful call\nto [`RedisModule_StreamIteratorStart()`](#RedisModule_StreamIteratorStart) and with the same key, it is safe to assume that\nan `REDISMODULE_ERR` return value means that there are no more entries.\n\nUse [`RedisModule_StreamIteratorNextField()`](#RedisModule_StreamIteratorNextField) to retrieve the fields and values.\nSee the example at [`RedisModule_StreamIteratorStart()`](#RedisModule_StreamIteratorStart).\n\n<span id=\"RedisModule_StreamIteratorNextField\"></span>"
    },
    {
      "id": "redismodule-streamiteratornextfield",
      "title": "`RedisModule_StreamIteratorNextField`",
      "role": "content",
      "text": "int RedisModule_StreamIteratorNextField(RedisModuleKey *key,\n                                            RedisModuleString **field_ptr,\n                                            RedisModuleString **value_ptr);\n\n**Available since:** 6.2.0\n\nRetrieves the next field of the current stream ID and its corresponding value\nin a stream iteration. This function should be called repeatedly after calling\n[`RedisModule_StreamIteratorNextID()`](#RedisModule_StreamIteratorNextID) to fetch each field-value pair.\n\n- `key`: Key where a stream iterator has been started.\n- `field_ptr`: This is where the field is returned.\n- `value_ptr`: This is where the value is returned.\n\nReturns `REDISMODULE_OK` and points `*field_ptr` and `*value_ptr` to freshly\nallocated `RedisModuleString` objects. The string objects are freed\nautomatically when the callback finishes if automatic memory is enabled. On\nfailure, `REDISMODULE_ERR` is returned and `errno` is set as follows:\n\n- EINVAL if called with a NULL key\n- ENOTSUP if the key refers to a value of a type other than stream or if the\n  key is empty\n- EBADF if no stream iterator is associated with the key\n- ENOENT if there are no more fields in the current stream entry\n\nIn practice, if [`RedisModule_StreamIteratorNextField()`](#RedisModule_StreamIteratorNextField) is called after a successful\ncall to [`RedisModule_StreamIteratorNextID()`](#RedisModule_StreamIteratorNextID) and with the same key, it is safe to assume\nthat an `REDISMODULE_ERR` return value means that there are no more fields.\n\nSee the example at [`RedisModule_StreamIteratorStart()`](#RedisModule_StreamIteratorStart).\n\n<span id=\"RedisModule_StreamIteratorDelete\"></span>"
    },
    {
      "id": "redismodule-streamiteratordelete",
      "title": "`RedisModule_StreamIteratorDelete`",
      "role": "content",
      "text": "int RedisModule_StreamIteratorDelete(RedisModuleKey *key);\n\n**Available since:** 6.2.0\n\nDeletes the current stream entry while iterating.\n\nThis function can be called after [`RedisModule_StreamIteratorNextID()`](#RedisModule_StreamIteratorNextID) or after any\ncalls to [`RedisModule_StreamIteratorNextField()`](#RedisModule_StreamIteratorNextField).\n\nReturns `REDISMODULE_OK` on success. On failure, `REDISMODULE_ERR` is returned\nand `errno` is set as follows:\n\n- EINVAL if key is NULL\n- ENOTSUP if the key is empty or is of another type than stream\n- EBADF if the key is not opened for writing, if no iterator has been started\n- ENOENT if the iterator has no current stream entry\n\n<span id=\"RedisModule_StreamTrimByLength\"></span>"
    },
    {
      "id": "redismodule-streamtrimbylength",
      "title": "`RedisModule_StreamTrimByLength`",
      "role": "content",
      "text": "long long RedisModule_StreamTrimByLength(RedisModuleKey *key,\n                                             int flags,\n                                             long long length);\n\n**Available since:** 6.2.0\n\nTrim a stream by length, similar to XTRIM with MAXLEN.\n\n- `key`: Key opened for writing.\n- `flags`: A bitfield of\n  - `REDISMODULE_STREAM_TRIM_APPROX`: Trim less if it improves performance,\n    like XTRIM with `~`.\n- `length`: The number of stream entries to keep after trimming.\n\nReturns the number of entries deleted. On failure, a negative value is\nreturned and `errno` is set as follows:\n\n- EINVAL if called with invalid arguments\n- ENOTSUP if the key is empty or of a type other than stream\n- EBADF if the key is not opened for writing\n\n<span id=\"RedisModule_StreamTrimByID\"></span>"
    },
    {
      "id": "redismodule-streamtrimbyid",
      "title": "`RedisModule_StreamTrimByID`",
      "role": "content",
      "text": "long long RedisModule_StreamTrimByID(RedisModuleKey *key,\n                                         int flags,\n                                         RedisModuleStreamID *id);\n\n**Available since:** 6.2.0\n\nTrim a stream by ID, similar to XTRIM with MINID.\n\n- `key`: Key opened for writing.\n- `flags`: A bitfield of\n  - `REDISMODULE_STREAM_TRIM_APPROX`: Trim less if it improves performance,\n    like XTRIM with `~`.\n- `id`: The smallest stream ID to keep after trimming.\n\nReturns the number of entries deleted. On failure, a negative value is\nreturned and `errno` is set as follows:\n\n- EINVAL if called with invalid arguments\n- ENOTSUP if the key is empty or of a type other than stream\n- EBADF if the key is not opened for writing\n\n<span id=\"section-calling-redis-commands-from-modules\"></span>"
    },
    {
      "id": "calling-redis-commands-from-modules",
      "title": "Calling Redis commands from modules",
      "role": "content",
      "text": "[`RedisModule_Call()`](#RedisModule_Call) sends a command to Redis. The remaining functions handle the reply.\n\n<span id=\"RedisModule_FreeCallReply\"></span>"
    },
    {
      "id": "redismodule-freecallreply",
      "title": "`RedisModule_FreeCallReply`",
      "role": "content",
      "text": "void RedisModule_FreeCallReply(RedisModuleCallReply *reply);\n\n**Available since:** 4.0.0\n\nFree a Call reply and all the nested replies it contains if it's an\narray.\n\n<span id=\"RedisModule_CallReplyType\"></span>"
    },
    {
      "id": "redismodule-callreplytype",
      "title": "`RedisModule_CallReplyType`",
      "role": "content",
      "text": "int RedisModule_CallReplyType(RedisModuleCallReply *reply);\n\n**Available since:** 4.0.0\n\nReturn the reply type as one of the following:\n\n- `REDISMODULE_REPLY_UNKNOWN`\n- `REDISMODULE_REPLY_STRING`\n- `REDISMODULE_REPLY_ERROR`\n- `REDISMODULE_REPLY_INTEGER`\n- `REDISMODULE_REPLY_ARRAY`\n- `REDISMODULE_REPLY_NULL`\n- `REDISMODULE_REPLY_MAP`\n- `REDISMODULE_REPLY_SET`\n- `REDISMODULE_REPLY_BOOL`\n- `REDISMODULE_REPLY_DOUBLE`\n- `REDISMODULE_REPLY_BIG_NUMBER`\n- `REDISMODULE_REPLY_VERBATIM_STRING`\n- `REDISMODULE_REPLY_ATTRIBUTE`\n- `REDISMODULE_REPLY_PROMISE`\n\n<span id=\"RedisModule_CallReplyLength\"></span>"
    },
    {
      "id": "redismodule-callreplylength",
      "title": "`RedisModule_CallReplyLength`",
      "role": "content",
      "text": "size_t RedisModule_CallReplyLength(RedisModuleCallReply *reply);\n\n**Available since:** 4.0.0\n\nReturn the reply type length, where applicable.\n\n<span id=\"RedisModule_CallReplyArrayElement\"></span>"
    },
    {
      "id": "redismodule-callreplyarrayelement",
      "title": "`RedisModule_CallReplyArrayElement`",
      "role": "content",
      "text": "RedisModuleCallReply *RedisModule_CallReplyArrayElement(RedisModuleCallReply *reply,\n                                                            size_t idx);\n\n**Available since:** 4.0.0\n\nReturn the 'idx'-th nested call reply element of an array reply, or NULL\nif the reply type is wrong or the index is out of range.\n\n<span id=\"RedisModule_CallReplyInteger\"></span>"
    },
    {
      "id": "redismodule-callreplyinteger",
      "title": "`RedisModule_CallReplyInteger`",
      "role": "content",
      "text": "long long RedisModule_CallReplyInteger(RedisModuleCallReply *reply);\n\n**Available since:** 4.0.0\n\nReturn the `long long` of an integer reply.\n\n<span id=\"RedisModule_CallReplyDouble\"></span>"
    },
    {
      "id": "redismodule-callreplydouble",
      "title": "`RedisModule_CallReplyDouble`",
      "role": "content",
      "text": "double RedisModule_CallReplyDouble(RedisModuleCallReply *reply);\n\n**Available since:** 7.0.0\n\nReturn the double value of a double reply.\n\n<span id=\"RedisModule_CallReplyBigNumber\"></span>"
    },
    {
      "id": "redismodule-callreplybignumber",
      "title": "`RedisModule_CallReplyBigNumber`",
      "role": "content",
      "text": "const char *RedisModule_CallReplyBigNumber(RedisModuleCallReply *reply,\n                                               size_t *len);\n\n**Available since:** 7.0.0\n\nReturn the big number value of a big number reply.\n\n<span id=\"RedisModule_CallReplyVerbatim\"></span>"
    },
    {
      "id": "redismodule-callreplyverbatim",
      "title": "`RedisModule_CallReplyVerbatim`",
      "role": "content",
      "text": "const char *RedisModule_CallReplyVerbatim(RedisModuleCallReply *reply,\n                                              size_t *len,\n                                              const char **format);\n\n**Available since:** 7.0.0\n\nReturn the value of a verbatim string reply,\nAn optional output argument can be given to get verbatim reply format.\n\n<span id=\"RedisModule_CallReplyBool\"></span>"
    },
    {
      "id": "redismodule-callreplybool",
      "title": "`RedisModule_CallReplyBool`",
      "role": "content",
      "text": "int RedisModule_CallReplyBool(RedisModuleCallReply *reply);\n\n**Available since:** 7.0.0\n\nReturn the Boolean value of a Boolean reply.\n\n<span id=\"RedisModule_CallReplySetElement\"></span>"
    },
    {
      "id": "redismodule-callreplysetelement",
      "title": "`RedisModule_CallReplySetElement`",
      "role": "content",
      "text": "RedisModuleCallReply *RedisModule_CallReplySetElement(RedisModuleCallReply *reply,\n                                                          size_t idx);\n\n**Available since:** 7.0.0\n\nReturn the 'idx'-th nested call reply element of a set reply, or NULL\nif the reply type is wrong or the index is out of range.\n\n<span id=\"RedisModule_CallReplyMapElement\"></span>"
    },
    {
      "id": "redismodule-callreplymapelement",
      "title": "`RedisModule_CallReplyMapElement`",
      "role": "content",
      "text": "int RedisModule_CallReplyMapElement(RedisModuleCallReply *reply,\n                                        size_t idx,\n                                        RedisModuleCallReply **key,\n                                        RedisModuleCallReply **val);\n\n**Available since:** 7.0.0\n\nRetrieve the 'idx'-th key and value of a map reply.\n\nReturns:\n- `REDISMODULE_OK` on success.\n- `REDISMODULE_ERR` if idx out of range or if the reply type is wrong.\n\nThe `key` and `value` arguments are used to return by reference, and may be\nNULL if not required.\n\n<span id=\"RedisModule_CallReplyAttribute\"></span>"
    },
    {
      "id": "redismodule-callreplyattribute",
      "title": "`RedisModule_CallReplyAttribute`",
      "role": "content",
      "text": "RedisModuleCallReply *RedisModule_CallReplyAttribute(RedisModuleCallReply *reply);\n\n**Available since:** 7.0.0\n\nReturn the attribute of the given reply, or NULL if no attribute exists.\n\n<span id=\"RedisModule_CallReplyAttributeElement\"></span>"
    },
    {
      "id": "redismodule-callreplyattributeelement",
      "title": "`RedisModule_CallReplyAttributeElement`",
      "role": "content",
      "text": "int RedisModule_CallReplyAttributeElement(RedisModuleCallReply *reply,\n                                              size_t idx,\n                                              RedisModuleCallReply **key,\n                                              RedisModuleCallReply **val);\n\n**Available since:** 7.0.0\n\nRetrieve the 'idx'-th key and value of an attribute reply.\n\nReturns:\n- `REDISMODULE_OK` on success.\n- `REDISMODULE_ERR` if idx out of range or if the reply type is wrong.\n\nThe `key` and `value` arguments are used to return by reference, and may be\nNULL if not required.\n\n<span id=\"RedisModule_CallReplyPromiseSetUnblockHandler\"></span>"
    },
    {
      "id": "redismodule-callreplypromisesetunblockhandler",
      "title": "`RedisModule_CallReplyPromiseSetUnblockHandler`",
      "role": "content",
      "text": "void RedisModule_CallReplyPromiseSetUnblockHandler(RedisModuleCallReply *reply,\n                                                       RedisModuleOnUnblocked on_unblock,\n                                                       void *private_data);\n\n**Available since:** 7.2.0\n\nSet unblock handler (callback and private data) on the given promise `RedisModuleCallReply`.\nThe given reply must be of promise type (`REDISMODULE_REPLY_PROMISE`).\n\n<span id=\"RedisModule_CallReplyPromiseAbort\"></span>"
    },
    {
      "id": "redismodule-callreplypromiseabort",
      "title": "`RedisModule_CallReplyPromiseAbort`",
      "role": "content",
      "text": "int RedisModule_CallReplyPromiseAbort(RedisModuleCallReply *reply,\n                                          void **private_data);\n\n**Available since:** 7.2.0\n\nAbort the execution of a given promise `RedisModuleCallReply`.\nreturn `REDMODULE_OK` in case the abort was done successfully and `REDISMODULE_ERR`\nif its not possible to abort the execution (execution already finished).\nIn case the execution was aborted (`REDMODULE_OK` was returned), the `private_data` out parameter\nwill be set with the value of the private data that was given on '[`RedisModule_CallReplyPromiseSetUnblockHandler`](#RedisModule_CallReplyPromiseSetUnblockHandler)'\nso the caller will be able to release the private data.\n\nIf the execution was aborted successfully, it is promised that the unblock handler will not be called.\nThat said, it is possible that the abort operation will successes but the operation will still continue.\nThis can happened if, for example, a module implements some blocking command and does not respect the\ndisconnect callback. For pure Redis commands this can not happened.\n\n<span id=\"RedisModule_CallReplyStringPtr\"></span>"
    },
    {
      "id": "redismodule-callreplystringptr",
      "title": "`RedisModule_CallReplyStringPtr`",
      "role": "content",
      "text": "const char *RedisModule_CallReplyStringPtr(RedisModuleCallReply *reply,\n                                               size_t *len);\n\n**Available since:** 4.0.0\n\nReturn the pointer and length of a string or error reply.\n\n<span id=\"RedisModule_CreateStringFromCallReply\"></span>"
    },
    {
      "id": "redismodule-createstringfromcallreply",
      "title": "`RedisModule_CreateStringFromCallReply`",
      "role": "content",
      "text": "RedisModuleString *RedisModule_CreateStringFromCallReply(RedisModuleCallReply *reply);\n\n**Available since:** 4.0.0\n\nReturn a new string object from a call reply of type string, error or\ninteger. Otherwise (wrong reply type) return NULL.\n\n<span id=\"RedisModule_SetContextUser\"></span>"
    },
    {
      "id": "redismodule-setcontextuser",
      "title": "`RedisModule_SetContextUser`",
      "role": "content",
      "text": "void RedisModule_SetContextUser(RedisModuleCtx *ctx,\n                                    const RedisModuleUser *user);\n\n**Available since:** 7.0.6\n\nModifies the user that [`RedisModule_Call`](#RedisModule_Call) will use (e.g. for ACL checks)\n\n<span id=\"RedisModule_Call\"></span>"
    },
    {
      "id": "redismodule-call",
      "title": "`RedisModule_Call`",
      "role": "content",
      "text": "RedisModuleCallReply *RedisModule_Call(RedisModuleCtx *ctx,\n                                           const char *cmdname,\n                                           const char *fmt,\n                                           ...);\n\n**Available since:** 4.0.0\n\nExported API to call any Redis command from modules.\n\n* **cmdname**: The Redis command to call.\n* **fmt**: A format specifier string for the command's arguments. Each\n  of the arguments should be specified by a valid type specification. The\n  format specifier can also contain the modifiers `!`, `A`, `3` and `R` which\n  don't have a corresponding argument.\n\n    * `b` -- The argument is a buffer and is immediately followed by another\n             argument that is the buffer's length.\n    * `c` -- The argument is a pointer to a plain C string (null-terminated).\n    * `l` -- The argument is a `long long` integer.\n    * `s` -- The argument is a RedisModuleString.\n    * `v` -- The argument(s) is a vector of RedisModuleString.\n    * `!` -- Sends the Redis command and its arguments to replicas and AOF.\n    * `A` -- Suppress AOF propagation, send only to replicas (requires `!`).\n    * `R` -- Suppress replicas propagation, send only to AOF (requires `!`).\n    * `3` -- Return a RESP3 reply. This will change the command reply.\n             e.g., HGETALL returns a map instead of a flat array.\n    * `0` -- Return the reply in auto mode, i.e. the reply format will be the\n             same as the client attached to the given RedisModuleCtx. This will\n             probably used when you want to pass the reply directly to the client.\n    * `C` -- Run a command as the user attached to the context.\n             User is either attached automatically via the client that directly\n             issued the command and created the context or via RedisModule_SetContextUser.\n             If the context is not directly created by an issued command (such as a\n             background context and no user was set on it via RedisModule_SetContextUser,\n             RedisModule_Call will fail.\n             Checks if the command can be executed according to ACL rules and causes\n             the command to run as the determined user, so that any future user\n             dependent activity, such as ACL checks within scripts will proceed as\n             expected.\n             Otherwise, the command will run as the Redis unrestricted user.\n             Upon sending a command from an internal connection, this flag is\n             ignored and the command will run as the Redis unrestricted user.\n    * `S` -- Run the command in a script mode, this means that it will raise\n             an error if a command which are not allowed inside a script\n             (flagged with the `deny-script` flag) is invoked (like SHUTDOWN).\n             In addition, on script mode, write commands are not allowed if there are\n             not enough good replicas (as configured with `min-replicas-to-write`)\n             or when the server is unable to persist to the disk.\n    * `W` -- Do not allow to run any write command (flagged with the `write` flag).\n    * `M` -- Do not allow `deny-oom` flagged commands when over the memory limit.\n    * `E` -- Return error as RedisModuleCallReply. If there is an error before\n             invoking the command, the error is returned using errno mechanism.\n             This flag allows to get the error also as an error CallReply with\n             relevant error message.\n    * 'D' -- A \"Dry Run\" mode. Return before executing the underlying call().\n             If everything succeeded, it will return with a NULL, otherwise it will\n             return with a CallReply object denoting the error, as if it was called with\n             the 'E' code.\n    * 'K' -- Allow running blocking commands. If enabled and the command gets blocked, a\n             special REDISMODULE_REPLY_PROMISE will be returned. This reply type\n             indicates that the command was blocked and the reply will be given asynchronously.\n             The module can use this reply object to set a handler which will be called when\n             the command gets unblocked using RedisModule_CallReplyPromiseSetUnblockHandler.\n             The handler must be set immediately after the command invocation (without releasing\n             the Redis lock in between). If the handler is not set, the blocking command will\n             still continue its execution but the reply will be ignored (fire and forget),\n             notice that this is dangerous in case of role change, as explained below.\n             The module can use RedisModule_CallReplyPromiseAbort to abort the command invocation\n             if it was not yet finished (see RedisModule_CallReplyPromiseAbort documentation for more\n             details). It is also the module's responsibility to abort the execution on role change, either by using\n             server event (to get notified when the instance becomes a replica) or relying on the disconnect\n             callback of the original client. Failing to do so can result in a write operation on a replica.\n             Unlike other call replies, promise call reply **must** be freed while the Redis GIL is locked.\n             Notice that on unblocking, the only promise is that the unblock handler will be called,\n             If the blocking RedisModule_Call caused the module to also block some real client (using RedisModule_BlockClient),\n             it is the module responsibility to unblock this client on the unblock handler.\n             On the unblock handler it is only allowed to perform the following:\n             * Calling additional Redis commands using RedisModule_Call\n             * Open keys using RedisModule_OpenKey\n             * Replicate data to the replica or AOF\n\n             Specifically, it is not allowed to call any Redis module API which are client related such as:\n             * RedisModule_Reply* API's\n             * RedisModule_BlockClient\n             * RedisModule_GetCurrentUserName\n\n* **...**: The actual arguments to the Redis command.\n\nOn success a `RedisModuleCallReply` object is returned, otherwise\nNULL is returned and errno is set to the following values:\n\n* EBADF: wrong format specifier.\n* EINVAL: wrong command arity.\n* ENOENT: command does not exist.\n* EPERM: operation in Cluster instance with key in non local slot.\n* EROFS: operation in Cluster instance when a write command is sent\n         in a readonly state.\n* ENETDOWN: operation in Cluster instance when cluster is down.\n* ENOTSUP: No ACL user for the specified module context\n* EACCES: Command cannot be executed, according to ACL rules\n* ENOSPC: Write or deny-oom command is not allowed\n* ESPIPE: Command not allowed on script mode\n\nExample code fragment:\n\n     reply = RedisModule_Call(ctx,\"INCRBY\",\"sc\",argv[1],\"10\");\n     if (RedisModule_CallReplyType(reply) == REDISMODULE_REPLY_INTEGER) {\n       long long myval = RedisModule_CallReplyInteger(reply);\n       // Do something with myval.\n     }\n\nThis API is documented here: [https://un5pn9hmggug.julianrbryant.com/docs/latest/develop/reference/modules/](https://un5pn9hmggug.julianrbryant.com/docs/latest/develop/reference/modules/)\n\n<span id=\"RedisModule_CallReplyProto\"></span>"
    },
    {
      "id": "redismodule-callreplyproto",
      "title": "`RedisModule_CallReplyProto`",
      "role": "content",
      "text": "const char *RedisModule_CallReplyProto(RedisModuleCallReply *reply,\n                                           size_t *len);\n\n**Available since:** 4.0.0\n\nReturn a pointer, and a length, to the protocol returned by the command\nthat returned the reply object.\n\n<span id=\"section-modules-data-types\"></span>"
    },
    {
      "id": "modules-data-types",
      "title": "Modules data types",
      "role": "content",
      "text": "When String DMA or using existing data structures is not enough, it is\npossible to create new data types from scratch and export them to\nRedis. The module must provide a set of callbacks for handling the\nnew values exported (for example in order to provide RDB saving/loading,\nAOF rewrite, and so forth). In this section we define this API.\n\n<span id=\"RedisModule_CreateDataType\"></span>"
    },
    {
      "id": "redismodule-createdatatype",
      "title": "`RedisModule_CreateDataType`",
      "role": "content",
      "text": "moduleType *RedisModule_CreateDataType(RedisModuleCtx *ctx,\n                                           const char *name,\n                                           int encver,\n                                           void *typemethods_ptr);\n\n**Available since:** 4.0.0\n\nRegister a new data type exported by the module. The parameters are the\nfollowing. Please for in depth documentation check the modules API\ndocumentation, especially [https://un5pn9hmggug.julianrbryant.com/docs/latest/develop/reference/modules/modules-native-types/](https://un5pn9hmggug.julianrbryant.com/docs/latest/develop/reference/modules/modules-native-types/).\n\n* **name**: A 9 characters data type name that MUST be unique in the Redis\n  Modules ecosystem. Be creative... and there will be no collisions. Use\n  the charset A-Z a-z 9-0, plus the two \"-_\" characters. A good\n  idea is to use, for example `<typename>-<vendor>`. For example\n  \"tree-AntZ\" may mean \"Tree data structure by @antirez\". To use both\n  lower case and upper case letters helps in order to prevent collisions.\n* **encver**: Encoding version, which is, the version of the serialization\n  that a module used in order to persist data. As long as the \"name\"\n  matches, the RDB loading will be dispatched to the type callbacks\n  whatever 'encver' is used, however the module can understand if\n  the encoding it must load are of an older version of the module.\n  For example the module \"tree-AntZ\" initially used encver=0. Later\n  after an upgrade, it started to serialize data in a different format\n  and to register the type with encver=1. However this module may\n  still load old data produced by an older version if the `rdb_load`\n  callback is able to check the encver value and act accordingly.\n  The encver must be a positive value between 0 and 1023.\n\n* **typemethods_ptr** is a pointer to a `RedisModuleTypeMethods` structure\n  that should be populated with the methods callbacks and structure\n  version, like in the following example:\n\n        RedisModuleTypeMethods tm = {\n            .version = REDISMODULE_TYPE_METHOD_VERSION,\n            .rdb_load = myType_RDBLoadCallBack,\n            .rdb_save = myType_RDBSaveCallBack,\n            .aof_rewrite = myType_AOFRewriteCallBack,\n            .free = myType_FreeCallBack,\n\n            // Optional fields\n            .digest = myType_DigestCallBack,\n            .mem_usage = myType_MemUsageCallBack,\n            .aux_load = myType_AuxRDBLoadCallBack,\n            .aux_save = myType_AuxRDBSaveCallBack,\n            .free_effort = myType_FreeEffortCallBack,\n            .unlink = myType_UnlinkCallBack,\n            .copy = myType_CopyCallback,\n            .defrag = myType_DefragCallback\n\n            // Enhanced optional fields\n            .mem_usage2 = myType_MemUsageCallBack2,\n            .free_effort2 = myType_FreeEffortCallBack2,\n            .unlink2 = myType_UnlinkCallBack2,\n            .copy2 = myType_CopyCallback2,\n        }\n\n* **rdb_load**: A callback function pointer that loads data from RDB files.\n* **rdb_save**: A callback function pointer that saves data to RDB files.\n* **aof_rewrite**: A callback function pointer that rewrites data as commands.\n* **digest**: A callback function pointer that is used for `DEBUG DIGEST`.\n* **free**: A callback function pointer that can free a type value.\n* **aux_save**: A callback function pointer that saves out of keyspace data to RDB files.\n  'when' argument is either `REDISMODULE_AUX_BEFORE_RDB` or `REDISMODULE_AUX_AFTER_RDB`.\n* **aux_load**: A callback function pointer that loads out of keyspace data from RDB files.\n  Similar to `aux_save`, returns `REDISMODULE_OK` on success, and ERR otherwise.\n* **free_effort**: A callback function pointer that used to determine whether the module's\n  memory needs to be lazy reclaimed. The module should return the complexity involved by\n  freeing the value. for example: how many pointers are gonna be freed. Note that if it \n  returns 0, we'll always do an async free.\n* **unlink**: A callback function pointer that used to notifies the module that the key has \n  been removed from the DB by redis, and may soon be freed by a background thread. Note that \n  it won't be called on FLUSHALL/FLUSHDB (both sync and async), and the module can use the \n  `RedisModuleEvent_FlushDB` to hook into that.\n* **copy**: A callback function pointer that is used to make a copy of the specified key.\n  The module is expected to perform a deep copy of the specified value and return it.\n  In addition, hints about the names of the source and destination keys is provided.\n  A NULL return value is considered an error and the copy operation fails.\n  Note: if the target key exists and is being overwritten, the copy callback will be\n  called first, followed by a free callback to the value that is being replaced.\n\n* **defrag**: A callback function pointer that is used to request the module to defrag\n  a key. The module should then iterate pointers and call the relevant `RedisModule_Defrag*()`\n  functions to defragment pointers or complex types. The module should continue\n  iterating as long as [`RedisModule_DefragShouldStop()`](#RedisModule_DefragShouldStop) returns a zero value, and return a\n  zero value if finished or non-zero value if more work is left to be done. If more work\n  needs to be done, [`RedisModule_DefragCursorSet()`](#RedisModule_DefragCursorSet) and [`RedisModule_DefragCursorGet()`](#RedisModule_DefragCursorGet) can be used to track\n  this work across different calls.\n  Normally, the defrag mechanism invokes the callback without a time limit, so\n  [`RedisModule_DefragShouldStop()`](#RedisModule_DefragShouldStop) always returns zero. The \"late defrag\" mechanism which has\n  a time limit and provides cursor support is used only for keys that are determined\n  to have significant internal complexity. To determine this, the defrag mechanism\n  uses the `free_effort` callback and the 'active-defrag-max-scan-fields' config directive.\n  NOTE: The value is passed as a `void**` and the function is expected to update the\n  pointer if the top-level value pointer is defragmented and consequently changes.\n\n* **mem_usage2**: Similar to `mem_usage`, but provides the `RedisModuleKeyOptCtx` parameter\n  so that meta information such as key name and db id can be obtained, and\n  the `sample_size` for size estimation (see MEMORY USAGE command).\n* **free_effort2**: Similar to `free_effort`, but provides the `RedisModuleKeyOptCtx` parameter\n  so that meta information such as key name and db id can be obtained.\n* **unlink2**: Similar to `unlink`, but provides the `RedisModuleKeyOptCtx` parameter\n  so that meta information such as key name and db id can be obtained.\n* **copy2**: Similar to `copy`, but provides the `RedisModuleKeyOptCtx` parameter\n  so that meta information such as key names and db ids can be obtained.\n* **aux_save2**: Similar to `aux_save`, but with small semantic change, if the module\n  saves nothing on this callback then no data about this aux field will be written to the\n  RDB and it will be possible to load the RDB even if the module is not loaded.\n\nNote: the module name \"AAAAAAAAA\" is reserved and produces an error, it\nhappens to be pretty lame as well.\n\nIf [`RedisModule_CreateDataType()`](#RedisModule_CreateDataType) is called outside of `RedisModule_OnLoad()` function,\nthere is already a module registering a type with the same name,\nor if the module name or encver is invalid, NULL is returned.\nOtherwise the new type is registered into Redis, and a reference of\ntype `RedisModuleType` is returned: the caller of the function should store\nthis reference into a global variable to make future use of it in the\nmodules type API, since a single module may register multiple types.\nExample code fragment:\n\n     static RedisModuleType *BalancedTreeType;\n\n     int RedisModule_OnLoad(RedisModuleCtx *ctx) {\n         // some code here ...\n         BalancedTreeType = RedisModule_CreateDataType(...);\n     }\n\n<span id=\"RedisModule_ModuleTypeSetValue\"></span>"
    },
    {
      "id": "redismodule-moduletypesetvalue",
      "title": "`RedisModule_ModuleTypeSetValue`",
      "role": "content",
      "text": "int RedisModule_ModuleTypeSetValue(RedisModuleKey *key,\n                                       moduleType *mt,\n                                       void *value);\n\n**Available since:** 4.0.0\n\nIf the key is open for writing, set the specified module type object\nas the value of the key, deleting the old value if any.\nOn success `REDISMODULE_OK` is returned. If the key is not open for\nwriting or there is an active iterator, `REDISMODULE_ERR` is returned.\n\n<span id=\"RedisModule_ModuleTypeGetType\"></span>"
    },
    {
      "id": "redismodule-moduletypegettype",
      "title": "`RedisModule_ModuleTypeGetType`",
      "role": "content",
      "text": "moduleType *RedisModule_ModuleTypeGetType(RedisModuleKey *key);\n\n**Available since:** 4.0.0\n\nAssuming [`RedisModule_KeyType()`](#RedisModule_KeyType) returned `REDISMODULE_KEYTYPE_MODULE` on\nthe key, returns the module type pointer of the value stored at key.\n\nIf the key is NULL, is not associated with a module type, or is empty,\nthen NULL is returned instead.\n\n<span id=\"RedisModule_ModuleTypeGetValue\"></span>"
    },
    {
      "id": "redismodule-moduletypegetvalue",
      "title": "`RedisModule_ModuleTypeGetValue`",
      "role": "content",
      "text": "void *RedisModule_ModuleTypeGetValue(RedisModuleKey *key);\n\n**Available since:** 4.0.0\n\nAssuming [`RedisModule_KeyType()`](#RedisModule_KeyType) returned `REDISMODULE_KEYTYPE_MODULE` on\nthe key, returns the module type low-level value stored at key, as\nit was set by the user via [`RedisModule_ModuleTypeSetValue()`](#RedisModule_ModuleTypeSetValue).\n\nIf the key is NULL, is not associated with a module type, or is empty,\nthen NULL is returned instead.\n\n<span id=\"section-rdb-loading-and-saving-functions\"></span>"
    },
    {
      "id": "rdb-loading-and-saving-functions",
      "title": "RDB loading and saving functions",
      "role": "content",
      "text": "<span id=\"RedisModule_IsIOError\"></span>"
    },
    {
      "id": "redismodule-isioerror",
      "title": "`RedisModule_IsIOError`",
      "role": "content",
      "text": "int RedisModule_IsIOError(RedisModuleIO *io);\n\n**Available since:** 6.0.0\n\nReturns true if any previous IO API failed.\nfor `Load*` APIs the `REDISMODULE_OPTIONS_HANDLE_IO_ERRORS` flag must be set with\n[`RedisModule_SetModuleOptions`](#RedisModule_SetModuleOptions) first.\n\n<span id=\"RedisModule_SaveUnsigned\"></span>"
    },
    {
      "id": "redismodule-saveunsigned",
      "title": "`RedisModule_SaveUnsigned`",
      "role": "content",
      "text": "void RedisModule_SaveUnsigned(RedisModuleIO *io, uint64_t value);\n\n**Available since:** 4.0.0\n\nSave an unsigned 64 bit value into the RDB file. This function should only\nbe called in the context of the `rdb_save` method of modules implementing new\ndata types.\n\n<span id=\"RedisModule_LoadUnsigned\"></span>"
    },
    {
      "id": "redismodule-loadunsigned",
      "title": "`RedisModule_LoadUnsigned`",
      "role": "content",
      "text": "uint64_t RedisModule_LoadUnsigned(RedisModuleIO *io);\n\n**Available since:** 4.0.0\n\nLoad an unsigned 64 bit value from the RDB file. This function should only\nbe called in the context of the `rdb_load` method of modules implementing\nnew data types.\n\n<span id=\"RedisModule_SaveSigned\"></span>"
    },
    {
      "id": "redismodule-savesigned",
      "title": "`RedisModule_SaveSigned`",
      "role": "content",
      "text": "void RedisModule_SaveSigned(RedisModuleIO *io, int64_t value);\n\n**Available since:** 4.0.0\n\nLike [`RedisModule_SaveUnsigned()`](#RedisModule_SaveUnsigned) but for signed 64 bit values.\n\n<span id=\"RedisModule_LoadSigned\"></span>"
    },
    {
      "id": "redismodule-loadsigned",
      "title": "`RedisModule_LoadSigned`",
      "role": "content",
      "text": "int64_t RedisModule_LoadSigned(RedisModuleIO *io);\n\n**Available since:** 4.0.0\n\nLike [`RedisModule_LoadUnsigned()`](#RedisModule_LoadUnsigned) but for signed 64 bit values.\n\n<span id=\"RedisModule_SaveString\"></span>"
    },
    {
      "id": "redismodule-savestring",
      "title": "`RedisModule_SaveString`",
      "role": "content",
      "text": "void RedisModule_SaveString(RedisModuleIO *io, RedisModuleString *s);\n\n**Available since:** 4.0.0\n\nIn the context of the `rdb_save` method of a module type, saves a\nstring into the RDB file taking as input a `RedisModuleString`.\n\nThe string can be later loaded with [`RedisModule_LoadString()`](#RedisModule_LoadString) or\nother Load family functions expecting a serialized string inside\nthe RDB file.\n\n<span id=\"RedisModule_SaveStringBuffer\"></span>"
    },
    {
      "id": "redismodule-savestringbuffer",
      "title": "`RedisModule_SaveStringBuffer`",
      "role": "content",
      "text": "void RedisModule_SaveStringBuffer(RedisModuleIO *io,\n                                      const char *str,\n                                      size_t len);\n\n**Available since:** 4.0.0\n\nLike [`RedisModule_SaveString()`](#RedisModule_SaveString) but takes a raw C pointer and length\nas input.\n\n<span id=\"RedisModule_LoadString\"></span>"
    },
    {
      "id": "redismodule-loadstring",
      "title": "`RedisModule_LoadString`",
      "role": "content",
      "text": "RedisModuleString *RedisModule_LoadString(RedisModuleIO *io);\n\n**Available since:** 4.0.0\n\nIn the context of the `rdb_load` method of a module data type, loads a string\nfrom the RDB file, that was previously saved with [`RedisModule_SaveString()`](#RedisModule_SaveString)\nfunctions family.\n\nThe returned string is a newly allocated `RedisModuleString` object, and\nthe user should at some point free it with a call to [`RedisModule_FreeString()`](#RedisModule_FreeString).\n\nIf the data structure does not store strings as `RedisModuleString` objects,\nthe similar function [`RedisModule_LoadStringBuffer()`](#RedisModule_LoadStringBuffer) could be used instead.\n\n<span id=\"RedisModule_LoadStringBuffer\"></span>"
    },
    {
      "id": "redismodule-loadstringbuffer",
      "title": "`RedisModule_LoadStringBuffer`",
      "role": "content",
      "text": "char *RedisModule_LoadStringBuffer(RedisModuleIO *io, size_t *lenptr);\n\n**Available since:** 4.0.0\n\nLike [`RedisModule_LoadString()`](#RedisModule_LoadString) but returns a heap allocated string that\nwas allocated with [`RedisModule_Alloc()`](#RedisModule_Alloc), and can be resized or freed with\n[`RedisModule_Realloc()`](#RedisModule_Realloc) or [`RedisModule_Free()`](#RedisModule_Free).\n\nThe size of the string is stored at '*lenptr' if not NULL.\nThe returned string is not automatically NULL terminated, it is loaded\nexactly as it was stored inside the RDB file.\n\n<span id=\"RedisModule_SaveDouble\"></span>"
    },
    {
      "id": "redismodule-savedouble",
      "title": "`RedisModule_SaveDouble`",
      "role": "content",
      "text": "void RedisModule_SaveDouble(RedisModuleIO *io, double value);\n\n**Available since:** 4.0.0\n\nIn the context of the `rdb_save` method of a module data type, saves a double\nvalue to the RDB file. The double can be a valid number, a NaN or infinity.\nIt is possible to load back the value with [`RedisModule_LoadDouble()`](#RedisModule_LoadDouble).\n\n<span id=\"RedisModule_LoadDouble\"></span>"
    },
    {
      "id": "redismodule-loaddouble",
      "title": "`RedisModule_LoadDouble`",
      "role": "content",
      "text": "double RedisModule_LoadDouble(RedisModuleIO *io);\n\n**Available since:** 4.0.0\n\nIn the context of the `rdb_save` method of a module data type, loads back the\ndouble value saved by [`RedisModule_SaveDouble()`](#RedisModule_SaveDouble).\n\n<span id=\"RedisModule_SaveFloat\"></span>"
    },
    {
      "id": "redismodule-savefloat",
      "title": "`RedisModule_SaveFloat`",
      "role": "content",
      "text": "void RedisModule_SaveFloat(RedisModuleIO *io, float value);\n\n**Available since:** 4.0.0\n\nIn the context of the `rdb_save` method of a module data type, saves a float\nvalue to the RDB file. The float can be a valid number, a NaN or infinity.\nIt is possible to load back the value with [`RedisModule_LoadFloat()`](#RedisModule_LoadFloat).\n\n<span id=\"RedisModule_LoadFloat\"></span>"
    },
    {
      "id": "redismodule-loadfloat",
      "title": "`RedisModule_LoadFloat`",
      "role": "content",
      "text": "float RedisModule_LoadFloat(RedisModuleIO *io);\n\n**Available since:** 4.0.0\n\nIn the context of the `rdb_save` method of a module data type, loads back the\nfloat value saved by [`RedisModule_SaveFloat()`](#RedisModule_SaveFloat).\n\n<span id=\"RedisModule_SaveLongDouble\"></span>"
    },
    {
      "id": "redismodule-savelongdouble",
      "title": "`RedisModule_SaveLongDouble`",
      "role": "content",
      "text": "void RedisModule_SaveLongDouble(RedisModuleIO *io, long double value);\n\n**Available since:** 6.0.0\n\nIn the context of the `rdb_save` method of a module data type, saves a long double\nvalue to the RDB file. The double can be a valid number, a NaN or infinity.\nIt is possible to load back the value with [`RedisModule_LoadLongDouble()`](#RedisModule_LoadLongDouble).\n\n<span id=\"RedisModule_LoadLongDouble\"></span>"
    },
    {
      "id": "redismodule-loadlongdouble",
      "title": "`RedisModule_LoadLongDouble`",
      "role": "content",
      "text": "long double RedisModule_LoadLongDouble(RedisModuleIO *io);\n\n**Available since:** 6.0.0\n\nIn the context of the `rdb_save` method of a module data type, loads back the\nlong double value saved by [`RedisModule_SaveLongDouble()`](#RedisModule_SaveLongDouble).\n\n<span id=\"section-key-digest-api-debug-digest-interface-for-modules-types\"></span>"
    },
    {
      "id": "key-digest-api-debug-digest-interface-for-modules-types",
      "title": "Key digest API (DEBUG DIGEST interface for modules types)",
      "role": "content",
      "text": "<span id=\"RedisModule_DigestAddStringBuffer\"></span>"
    },
    {
      "id": "redismodule-digestaddstringbuffer",
      "title": "`RedisModule_DigestAddStringBuffer`",
      "role": "content",
      "text": "void RedisModule_DigestAddStringBuffer(RedisModuleDigest *md,\n                                           const char *ele,\n                                           size_t len);\n\n**Available since:** 4.0.0\n\nAdd a new element to the digest. This function can be called multiple times\none element after the other, for all the elements that constitute a given\ndata structure. The function call must be followed by the call to\n[`RedisModule_DigestEndSequence`](#RedisModule_DigestEndSequence) eventually, when all the elements that are\nalways in a given order are added. See the Redis Modules data types\ndocumentation for more info. However this is a quick example that uses Redis\ndata types as an example.\n\nTo add a sequence of unordered elements (for example in the case of a Redis\nSet), the pattern to use is:\n\n    foreach element {\n        AddElement(element);\n        EndSequence();\n    }\n\nBecause Sets are not ordered, so every element added has a position that\ndoes not depend from the other. However if instead our elements are\nordered in pairs, like field-value pairs of a Hash, then one should\nuse:\n\n    foreach key,value {\n        AddElement(key);\n        AddElement(value);\n        EndSequence();\n    }\n\nBecause the key and value will be always in the above order, while instead\nthe single key-value pairs, can appear in any position into a Redis hash.\n\nA list of ordered elements would be implemented with:\n\n    foreach element {\n        AddElement(element);\n    }\n    EndSequence();\n\n<span id=\"RedisModule_DigestAddLongLong\"></span>"
    },
    {
      "id": "redismodule-digestaddlonglong",
      "title": "`RedisModule_DigestAddLongLong`",
      "role": "content",
      "text": "void RedisModule_DigestAddLongLong(RedisModuleDigest *md, long long ll);\n\n**Available since:** 4.0.0\n\nLike [`RedisModule_DigestAddStringBuffer()`](#RedisModule_DigestAddStringBuffer) but takes a `long long` as input\nthat gets converted into a string before adding it to the digest.\n\n<span id=\"RedisModule_DigestEndSequence\"></span>"
    },
    {
      "id": "redismodule-digestendsequence",
      "title": "`RedisModule_DigestEndSequence`",
      "role": "content",
      "text": "void RedisModule_DigestEndSequence(RedisModuleDigest *md);\n\n**Available since:** 4.0.0\n\nSee the documentation for `RedisModule_DigestAddElement()`.\n\n<span id=\"RedisModule_LoadDataTypeFromStringEncver\"></span>"
    },
    {
      "id": "redismodule-loaddatatypefromstringencver",
      "title": "`RedisModule_LoadDataTypeFromStringEncver`",
      "role": "content",
      "text": "void *RedisModule_LoadDataTypeFromStringEncver(const RedisModuleString *str,\n                                                   const moduleType *mt,\n                                                   int encver);\n\n**Available since:** 7.0.0\n\nDecode a serialized representation of a module data type 'mt', in a specific encoding version 'encver'\nfrom string 'str' and return a newly allocated value, or NULL if decoding failed.\n\nThis call basically reuses the '`rdb_load`' callback which module data types\nimplement in order to allow a module to arbitrarily serialize/de-serialize\nkeys, similar to how the Redis 'DUMP' and 'RESTORE' commands are implemented.\n\nModules should generally use the `REDISMODULE_OPTIONS_HANDLE_IO_ERRORS` flag and\nmake sure the de-serialization code properly checks and handles IO errors\n(freeing allocated buffers and returning a NULL).\n\nIf this is NOT done, Redis will handle corrupted (or just truncated) serialized\ndata by producing an error message and terminating the process.\n\n<span id=\"RedisModule_LoadDataTypeFromString\"></span>"
    },
    {
      "id": "redismodule-loaddatatypefromstring",
      "title": "`RedisModule_LoadDataTypeFromString`",
      "role": "content",
      "text": "void *RedisModule_LoadDataTypeFromString(const RedisModuleString *str,\n                                             const moduleType *mt);\n\n**Available since:** 6.0.0\n\nSimilar to [`RedisModule_LoadDataTypeFromStringEncver`](#RedisModule_LoadDataTypeFromStringEncver), original version of the API, kept\nfor backward compatibility.\n\n<span id=\"RedisModule_SaveDataTypeToString\"></span>"
    },
    {
      "id": "redismodule-savedatatypetostring",
      "title": "`RedisModule_SaveDataTypeToString`",
      "role": "content",
      "text": "RedisModuleString *RedisModule_SaveDataTypeToString(RedisModuleCtx *ctx,\n                                                        void *data,\n                                                        const moduleType *mt);\n\n**Available since:** 6.0.0\n\nEncode a module data type 'mt' value 'data' into serialized form, and return it\nas a newly allocated `RedisModuleString`.\n\nThis call basically reuses the '`rdb_save`' callback which module data types\nimplement in order to allow a module to arbitrarily serialize/de-serialize\nkeys, similar to how the Redis 'DUMP' and 'RESTORE' commands are implemented.\n\n<span id=\"RedisModule_GetKeyNameFromDigest\"></span>"
    },
    {
      "id": "redismodule-getkeynamefromdigest",
      "title": "`RedisModule_GetKeyNameFromDigest`",
      "role": "content",
      "text": "const RedisModuleString *RedisModule_GetKeyNameFromDigest(RedisModuleDigest *dig);\n\n**Available since:** 7.0.0\n\nReturns the name of the key currently being processed.\n\n<span id=\"RedisModule_GetDbIdFromDigest\"></span>"
    },
    {
      "id": "redismodule-getdbidfromdigest",
      "title": "`RedisModule_GetDbIdFromDigest`",
      "role": "content",
      "text": "int RedisModule_GetDbIdFromDigest(RedisModuleDigest *dig);\n\n**Available since:** 7.0.0\n\nReturns the database id of the key currently being processed.\n\n<span id=\"section-aof-api-for-modules-data-types\"></span>"
    },
    {
      "id": "aof-api-for-modules-data-types",
      "title": "AOF API for modules data types",
      "role": "content",
      "text": "<span id=\"RedisModule_EmitAOF\"></span>"
    },
    {
      "id": "redismodule-emitaof",
      "title": "`RedisModule_EmitAOF`",
      "role": "content",
      "text": "void RedisModule_EmitAOF(RedisModuleIO *io,\n                             const char *cmdname,\n                             const char *fmt,\n                             ...);\n\n**Available since:** 4.0.0\n\nEmits a command into the AOF during the AOF rewriting process. This function\nis only called in the context of the `aof_rewrite` method of data types exported\nby a module. The command works exactly like [`RedisModule_Call()`](#RedisModule_Call) in the way\nthe parameters are passed, but it does not return anything as the error\nhandling is performed by Redis itself.\n\n<span id=\"section-io-context-handling\"></span>"
    },
    {
      "id": "io-context-handling",
      "title": "IO context handling",
      "role": "content",
      "text": "<span id=\"RedisModule_GetKeyNameFromIO\"></span>"
    },
    {
      "id": "redismodule-getkeynamefromio",
      "title": "`RedisModule_GetKeyNameFromIO`",
      "role": "content",
      "text": "const RedisModuleString *RedisModule_GetKeyNameFromIO(RedisModuleIO *io);\n\n**Available since:** 5.0.5\n\nReturns the name of the key currently being processed.\nThere is no guarantee that the key name is always available, so this may return NULL.\n\n<span id=\"RedisModule_GetKeyNameFromModuleKey\"></span>"
    },
    {
      "id": "redismodule-getkeynamefrommodulekey",
      "title": "`RedisModule_GetKeyNameFromModuleKey`",
      "role": "content",
      "text": "const RedisModuleString *RedisModule_GetKeyNameFromModuleKey(RedisModuleKey *key);\n\n**Available since:** 6.0.0\n\nReturns a `RedisModuleString` with the name of the key from `RedisModuleKey`.\n\n<span id=\"RedisModule_GetDbIdFromModuleKey\"></span>"
    },
    {
      "id": "redismodule-getdbidfrommodulekey",
      "title": "`RedisModule_GetDbIdFromModuleKey`",
      "role": "content",
      "text": "int RedisModule_GetDbIdFromModuleKey(RedisModuleKey *key);\n\n**Available since:** 7.0.0\n\nReturns a database id of the key from `RedisModuleKey`.\n\n<span id=\"RedisModule_GetDbIdFromIO\"></span>"
    },
    {
      "id": "redismodule-getdbidfromio",
      "title": "`RedisModule_GetDbIdFromIO`",
      "role": "content",
      "text": "int RedisModule_GetDbIdFromIO(RedisModuleIO *io);\n\n**Available since:** 7.0.0\n\nReturns the database id of the key currently being processed.\nThere is no guarantee that this info is always available, so this may return -1.\n\n<span id=\"section-logging\"></span>"
    },
    {
      "id": "logging",
      "title": "Logging",
      "role": "content",
      "text": "<span id=\"RedisModule_Log\"></span>"
    },
    {
      "id": "redismodule-log",
      "title": "`RedisModule_Log`",
      "role": "content",
      "text": "void RedisModule_Log(RedisModuleCtx *ctx,\n                         const char *levelstr,\n                         const char *fmt,\n                         ...);\n\n**Available since:** 4.0.0\n\nProduces a log message to the standard Redis log, the format accepts\nprintf-alike specifiers, while level is a string describing the log\nlevel to use when emitting the log, and must be one of the following:\n\n* \"debug\" (`REDISMODULE_LOGLEVEL_DEBUG`)\n* \"verbose\" (`REDISMODULE_LOGLEVEL_VERBOSE`)\n* \"notice\" (`REDISMODULE_LOGLEVEL_NOTICE`)\n* \"warning\" (`REDISMODULE_LOGLEVEL_WARNING`)\n\nIf the specified log level is invalid, verbose is used by default.\nThere is a fixed limit to the length of the log line this function is able\nto emit, this limit is not specified but is guaranteed to be more than\na few lines of text.\n\nThe ctx argument may be NULL if cannot be provided in the context of the\ncaller for instance threads or callbacks, in which case a generic \"module\"\nwill be used instead of the module name.\n\n<span id=\"RedisModule_LogIOError\"></span>"
    },
    {
      "id": "redismodule-logioerror",
      "title": "`RedisModule_LogIOError`",
      "role": "content",
      "text": "void RedisModule_LogIOError(RedisModuleIO *io,\n                                const char *levelstr,\n                                const char *fmt,\n                                ...);\n\n**Available since:** 4.0.0\n\nLog errors from RDB / AOF serialization callbacks.\n\nThis function should be used when a callback is returning a critical\nerror to the caller since cannot load or save the data for some\ncritical reason.\n\n<span id=\"RedisModule__Assert\"></span>"
    },
    {
      "id": "redismodule-assert",
      "title": "`RedisModule__Assert`",
      "role": "content",
      "text": "void RedisModule__Assert(const char *estr, const char *file, int line);\n\n**Available since:** 6.0.0\n\nRedis-like assert function.\n\nThe macro `RedisModule_Assert(expression)` is recommended, rather than\ncalling this function directly.\n\nA failed assertion will shut down the server and produce logging information\nthat looks identical to information generated by Redis itself.\n\n<span id=\"RedisModule_LatencyAddSample\"></span>"
    },
    {
      "id": "redismodule-latencyaddsample",
      "title": "`RedisModule_LatencyAddSample`",
      "role": "content",
      "text": "void RedisModule_LatencyAddSample(const char *event, mstime_t latency);\n\n**Available since:** 6.0.0\n\nAllows adding event to the latency monitor to be observed by the LATENCY\ncommand. The call is skipped if the latency is smaller than the configured\nlatency-monitor-threshold.\n\n<span id=\"section-blocking-clients-from-modules\"></span>"
    },
    {
      "id": "blocking-clients-from-modules",
      "title": "Blocking clients from modules",
      "role": "content",
      "text": "For a guide about blocking commands in modules, see\n[https://un5pn9hmggug.julianrbryant.com/docs/latest/develop/reference/modules/modules-blocking-ops/](https://un5pn9hmggug.julianrbryant.com/docs/latest/develop/reference/modules/modules-blocking-ops/).\n\n<span id=\"RedisModule_RegisterAuthCallback\"></span>"
    },
    {
      "id": "redismodule-registerauthcallback",
      "title": "`RedisModule_RegisterAuthCallback`",
      "role": "content",
      "text": "void RedisModule_RegisterAuthCallback(RedisModuleCtx *ctx,\n                                          RedisModuleAuthCallback cb);\n\n**Available since:** 7.2.0\n\nThis API registers a callback to execute in addition to normal password based authentication.\nMultiple callbacks can be registered across different modules. When a Module is unloaded, all the\nauth callbacks registered by it are unregistered.\nThe callbacks are attempted (in the order of most recently registered first) when the AUTH/HELLO\n(with AUTH field provided) commands are called.\nThe callbacks will be called with a module context along with a username and a password, and are\nexpected to take one of the following actions:\n(1) Authenticate - Use the `RedisModule_AuthenticateClient`* API and return `REDISMODULE_AUTH_HANDLED`.\nThis will immediately end the auth chain as successful and add the OK reply.\n(2) Deny Authentication - Return `REDISMODULE_AUTH_HANDLED` without authenticating or blocking the\nclient. Optionally, `err` can be set to a custom error message and `err` will be automatically\nfreed by the server.\nThis will immediately end the auth chain as unsuccessful and add the ERR reply.\n(3) Block a client on authentication - Use the [`RedisModule_BlockClientOnAuth`](#RedisModule_BlockClientOnAuth) API and return\n`REDISMODULE_AUTH_HANDLED`. Here, the client will be blocked until the [`RedisModule_UnblockClient`](#RedisModule_UnblockClient) API is used\nwhich will trigger the auth reply callback (provided through the [`RedisModule_BlockClientOnAuth`](#RedisModule_BlockClientOnAuth)).\nIn this reply callback, the Module should authenticate, deny or skip handling authentication.\n(4) Skip handling Authentication - Return `REDISMODULE_AUTH_NOT_HANDLED` without blocking the\nclient. This will allow the engine to attempt the next module auth callback.\nIf none of the callbacks authenticate or deny auth, then password based auth is attempted and\nwill authenticate or add failure logs and reply to the clients accordingly.\n\nNote: If a client is disconnected while it was in the middle of blocking module auth, that\noccurrence of the AUTH or HELLO command will not be tracked in the INFO command stats.\n\nThe following is an example of how non-blocking module based authentication can be used:\n\n     int auth_cb(RedisModuleCtx *ctx, RedisModuleString *username, RedisModuleString *password, RedisModuleString **err) {\n         const char *user = RedisModule_StringPtrLen(username, NULL);\n         const char *pwd = RedisModule_StringPtrLen(password, NULL);\n         if (!strcmp(user,\"foo\") && !strcmp(pwd,\"valid_password\")) {\n             RedisModule_AuthenticateClientWithACLUser(ctx, \"foo\", 3, NULL, NULL, NULL);\n             return REDISMODULE_AUTH_HANDLED;\n         }\n\n         else if (!strcmp(user,\"foo\") && !strcmp(pwd,\"wrong_password\")) {\n             RedisModuleString *log = RedisModule_CreateString(ctx, \"Module Auth\", 11);\n             RedisModule_ACLAddLogEntryByUserName(ctx, username, log, REDISMODULE_ACL_LOG_AUTH);\n             RedisModule_FreeString(ctx, log);\n             const char *err_msg = \"Auth denied by Misc Module.\";\n             *err = RedisModule_CreateString(ctx, err_msg, strlen(err_msg));\n             return REDISMODULE_AUTH_HANDLED;\n         }\n         return REDISMODULE_AUTH_NOT_HANDLED;\n      }\n\n     int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {\n         if (RedisModule_Init(ctx,\"authmodule\",1,REDISMODULE_APIVER_1)== REDISMODULE_ERR)\n             return REDISMODULE_ERR;\n         RedisModule_RegisterAuthCallback(ctx, auth_cb);\n         return REDISMODULE_OK;\n     }\n\n<span id=\"RedisModule_BlockClient\"></span>"
    },
    {
      "id": "redismodule-blockclient",
      "title": "`RedisModule_BlockClient`",
      "role": "content",
      "text": "RedisModuleBlockedClient *RedisModule_BlockClient(RedisModuleCtx *ctx,\n                                                      RedisModuleCmdFunc reply_callback,\n                                                      ;\n\n**Available since:** 4.0.0\n\nBlock a client in the context of a blocking command, returning a handle\nwhich will be used, later, in order to unblock the client with a call to\n[`RedisModule_UnblockClient()`](#RedisModule_UnblockClient). The arguments specify callback functions\nand a timeout after which the client is unblocked.\n\nThe callbacks are called in the following contexts:\n\n    reply_callback:   called after a successful RedisModule_UnblockClient()\n                      call in order to reply to the client and unblock it.\n\n    timeout_callback: called when the timeout is reached or if `CLIENT UNBLOCK`\n                      is invoked, in order to send an error to the client.\n\n    free_privdata:    called in order to free the private data that is passed\n                      by RedisModule_UnblockClient() call.\n\nNote: [`RedisModule_UnblockClient`](#RedisModule_UnblockClient) should be called for every blocked client,\n      even if client was killed, timed-out or disconnected. Failing to do so\n      will result in memory leaks.\n\nThere are some cases where [`RedisModule_BlockClient()`](#RedisModule_BlockClient) cannot be used:\n\n1. If the client is a Lua script.\n2. If the client is executing a MULTI block.\n\nIn these cases, a call to [`RedisModule_BlockClient()`](#RedisModule_BlockClient) will **not** block the\nclient, but instead produce a specific error reply.\n\nA module that registers a `timeout_callback` function can also be unblocked\nusing the `CLIENT UNBLOCK` command, which will trigger the timeout callback.\nIf a callback function is not registered, then the blocked client will be\ntreated as if it is not in a blocked state and `CLIENT UNBLOCK` will return\na zero value.\n\nMeasuring background time: By default the time spent in the blocked command\nis not account for the total command duration. To include such time you should\nuse [`RedisModule_BlockedClientMeasureTimeStart()`](#RedisModule_BlockedClientMeasureTimeStart) and [`RedisModule_BlockedClientMeasureTimeEnd()`](#RedisModule_BlockedClientMeasureTimeEnd) one,\nor multiple times within the blocking command background work.\n\n<span id=\"RedisModule_BlockClientOnAuth\"></span>"
    },
    {
      "id": "redismodule-blockclientonauth",
      "title": "`RedisModule_BlockClientOnAuth`",
      "role": "content",
      "text": "RedisModuleBlockedClient *RedisModule_BlockClientOnAuth(RedisModuleCtx *ctx,\n                                                            RedisModuleAuthCallback reply_callback,\n                                                            ;\n\n**Available since:** 7.2.0\n\nBlock the current client for module authentication in the background. If module auth is not in\nprogress on the client, the API returns NULL. Otherwise, the client is blocked and the `RedisModule_BlockedClient`\nis returned similar to the [`RedisModule_BlockClient`](#RedisModule_BlockClient) API.\nNote: Only use this API from the context of a module auth callback.\n\n<span id=\"RedisModule_BlockClientGetPrivateData\"></span>"
    },
    {
      "id": "redismodule-blockclientgetprivatedata",
      "title": "`RedisModule_BlockClientGetPrivateData`",
      "role": "content",
      "text": "void *RedisModule_BlockClientGetPrivateData(RedisModuleBlockedClient *blocked_client);\n\n**Available since:** 7.2.0\n\nGet the private data that was previusely set on a blocked client\n\n<span id=\"RedisModule_BlockClientSetPrivateData\"></span>"
    },
    {
      "id": "redismodule-blockclientsetprivatedata",
      "title": "`RedisModule_BlockClientSetPrivateData`",
      "role": "content",
      "text": "void RedisModule_BlockClientSetPrivateData(RedisModuleBlockedClient *blocked_client,\n                                               void *private_data);\n\n**Available since:** 7.2.0\n\nSet private data on a blocked client\n\n<span id=\"RedisModule_BlockClientOnKeys\"></span>"
    },
    {
      "id": "redismodule-blockclientonkeys",
      "title": "`RedisModule_BlockClientOnKeys`",
      "role": "content",
      "text": "RedisModuleBlockedClient *RedisModule_BlockClientOnKeys(RedisModuleCtx *ctx,\n                                                            RedisModuleCmdFunc reply_callback,\n                                                            ;\n\n**Available since:** 6.0.0\n\nThis call is similar to [`RedisModule_BlockClient()`](#RedisModule_BlockClient), however in this case we\ndon't just block the client, but also ask Redis to unblock it automatically\nonce certain keys become \"ready\", that is, contain more data.\n\nBasically this is similar to what a typical Redis command usually does,\nlike BLPOP or BZPOPMAX: the client blocks if it cannot be served ASAP,\nand later when the key receives new data (a list push for instance), the\nclient is unblocked and served.\n\nHowever in the case of this module API, when the client is unblocked?\n\n1. If you block on a key of a type that has blocking operations associated,\n   like a list, a sorted set, a stream, and so forth, the client may be\n   unblocked once the relevant key is targeted by an operation that normally\n   unblocks the native blocking operations for that type. So if we block\n   on a list key, an RPUSH command may unblock our client and so forth.\n2. If you are implementing your native data type, or if you want to add new\n   unblocking conditions in addition to \"1\", you can call the modules API\n   [`RedisModule_SignalKeyAsReady()`](#RedisModule_SignalKeyAsReady).\n\nAnyway we can't be sure if the client should be unblocked just because the\nkey is signaled as ready: for instance a successive operation may change the\nkey, or a client in queue before this one can be served, modifying the key\nas well and making it empty again. So when a client is blocked with\n[`RedisModule_BlockClientOnKeys()`](#RedisModule_BlockClientOnKeys) the reply callback is not called after\n[`RedisModule_UnblockClient()`](#RedisModule_UnblockClient) is called, but every time a key is signaled as ready:\nif the reply callback can serve the client, it returns `REDISMODULE_OK`\nand the client is unblocked, otherwise it will return `REDISMODULE_ERR`\nand we'll try again later.\n\nThe reply callback can access the key that was signaled as ready by\ncalling the API [`RedisModule_GetBlockedClientReadyKey()`](#RedisModule_GetBlockedClientReadyKey), that returns\njust the string name of the key as a `RedisModuleString` object.\n\nThanks to this system we can setup complex blocking scenarios, like\nunblocking a client only if a list contains at least 5 items or other\nmore fancy logics.\n\nNote that another difference with [`RedisModule_BlockClient()`](#RedisModule_BlockClient), is that here\nwe pass the private data directly when blocking the client: it will\nbe accessible later in the reply callback. Normally when blocking with\n[`RedisModule_BlockClient()`](#RedisModule_BlockClient) the private data to reply to the client is\npassed when calling [`RedisModule_UnblockClient()`](#RedisModule_UnblockClient) but here the unblocking\nis performed by Redis itself, so we need to have some private data before\nhand. The private data is used to store any information about the specific\nunblocking operation that you are implementing. Such information will be\nfreed using the `free_privdata` callback provided by the user.\n\nHowever the reply callback will be able to access the argument vector of\nthe command, so the private data is often not needed.\n\nNote: Under normal circumstances [`RedisModule_UnblockClient`](#RedisModule_UnblockClient) should not be\n      called for clients that are blocked on keys (Either the key will\n      become ready or a timeout will occur). If for some reason you do want\n      to call RedisModule_UnblockClient it is possible: Client will be\n      handled as if it were timed-out (You must implement the timeout\n      callback in that case).\n\n<span id=\"RedisModule_BlockClientOnKeysWithFlags\"></span>"
    },
    {
      "id": "redismodule-blockclientonkeyswithflags",
      "title": "`RedisModule_BlockClientOnKeysWithFlags`",
      "role": "content",
      "text": "RedisModuleBlockedClient *RedisModule_BlockClientOnKeysWithFlags(RedisModuleCtx *ctx,\n                                                                     RedisModuleCmdFunc reply_callback,\n                                                                     ;\n\n**Available since:** 7.2.0\n\nSame as [`RedisModule_BlockClientOnKeys`](#RedisModule_BlockClientOnKeys), but can take `REDISMODULE_BLOCK_`* flags\nCan be either `REDISMODULE_BLOCK_UNBLOCK_DEFAULT`, which means default behavior (same\nas calling [`RedisModule_BlockClientOnKeys`](#RedisModule_BlockClientOnKeys))\n\nThe flags is a bit mask of these:\n\n- `REDISMODULE_BLOCK_UNBLOCK_DELETED`: The clients should to be awakened in case any of `keys` are deleted.\n                                       Mostly useful for commands that require the key to exist (like XREADGROUP)\n\n<span id=\"RedisModule_SignalKeyAsReady\"></span>"
    },
    {
      "id": "redismodule-signalkeyasready",
      "title": "`RedisModule_SignalKeyAsReady`",
      "role": "content",
      "text": "void RedisModule_SignalKeyAsReady(RedisModuleCtx *ctx, RedisModuleString *key);\n\n**Available since:** 6.0.0\n\nThis function is used in order to potentially unblock a client blocked\non keys with [`RedisModule_BlockClientOnKeys()`](#RedisModule_BlockClientOnKeys). When this function is called,\nall the clients blocked for this key will get their `reply_callback` called.\n\n<span id=\"RedisModule_UnblockClient\"></span>"
    },
    {
      "id": "redismodule-unblockclient",
      "title": "`RedisModule_UnblockClient`",
      "role": "content",
      "text": "int RedisModule_UnblockClient(RedisModuleBlockedClient *bc, void *privdata);\n\n**Available since:** 4.0.0\n\nUnblock a client blocked by `RedisModule_BlockedClient`. This will trigger\nthe reply callbacks to be called in order to reply to the client.\nThe 'privdata' argument will be accessible by the reply callback, so\nthe caller of this function can pass any value that is needed in order to\nactually reply to the client.\n\nA common usage for 'privdata' is a thread that computes something that\nneeds to be passed to the client, included but not limited some slow\nto compute reply or some reply obtained via networking.\n\nNote 1: this function can be called from threads spawned by the module.\n\nNote 2: when we unblock a client that is blocked for keys using the API\n[`RedisModule_BlockClientOnKeys()`](#RedisModule_BlockClientOnKeys), the privdata argument here is not used.\nUnblocking a client that was blocked for keys using this API will still\nrequire the client to get some reply, so the function will use the\n\"timeout\" handler in order to do so (The privdata provided in\n[`RedisModule_BlockClientOnKeys()`](#RedisModule_BlockClientOnKeys) is accessible from the timeout\ncallback via [`RedisModule_GetBlockedClientPrivateData`](#RedisModule_GetBlockedClientPrivateData)).\n\n<span id=\"RedisModule_AbortBlock\"></span>"
    },
    {
      "id": "redismodule-abortblock",
      "title": "`RedisModule_AbortBlock`",
      "role": "content",
      "text": "int RedisModule_AbortBlock(RedisModuleBlockedClient *bc);\n\n**Available since:** 4.0.0\n\nAbort a blocked client blocking operation: the client will be unblocked\nwithout firing any callback.\n\n<span id=\"RedisModule_SetDisconnectCallback\"></span>"
    },
    {
      "id": "redismodule-setdisconnectcallback",
      "title": "`RedisModule_SetDisconnectCallback`",
      "role": "content",
      "text": "void RedisModule_SetDisconnectCallback(RedisModuleBlockedClient *bc,\n                                           RedisModuleDisconnectFunc callback);\n\n**Available since:** 5.0.0\n\nSet a callback that will be called if a blocked client disconnects\nbefore the module has a chance to call [`RedisModule_UnblockClient()`](#RedisModule_UnblockClient)\n\nUsually what you want to do there, is to cleanup your module state\nso that you can call [`RedisModule_UnblockClient()`](#RedisModule_UnblockClient) safely, otherwise\nthe client will remain blocked forever if the timeout is large.\n\nNotes:\n\n1. It is not safe to call Reply* family functions here, it is also\n   useless since the client is gone.\n\n2. This callback is not called if the client disconnects because of\n   a timeout. In such a case, the client is unblocked automatically\n   and the timeout callback is called.\n\n<span id=\"RedisModule_IsBlockedReplyRequest\"></span>"
    },
    {
      "id": "redismodule-isblockedreplyrequest",
      "title": "`RedisModule_IsBlockedReplyRequest`",
      "role": "content",
      "text": "int RedisModule_IsBlockedReplyRequest(RedisModuleCtx *ctx);\n\n**Available since:** 4.0.0\n\nReturn non-zero if a module command was called in order to fill the\nreply for a blocked client.\n\n<span id=\"RedisModule_IsBlockedTimeoutRequest\"></span>"
    },
    {
      "id": "redismodule-isblockedtimeoutrequest",
      "title": "`RedisModule_IsBlockedTimeoutRequest`",
      "role": "content",
      "text": "int RedisModule_IsBlockedTimeoutRequest(RedisModuleCtx *ctx);\n\n**Available since:** 4.0.0\n\nReturn non-zero if a module command was called in order to fill the\nreply for a blocked client that timed out.\n\n<span id=\"RedisModule_GetBlockedClientPrivateData\"></span>"
    },
    {
      "id": "redismodule-getblockedclientprivatedata",
      "title": "`RedisModule_GetBlockedClientPrivateData`",
      "role": "content",
      "text": "void *RedisModule_GetBlockedClientPrivateData(RedisModuleCtx *ctx);\n\n**Available since:** 4.0.0\n\nGet the private data set by [`RedisModule_UnblockClient()`](#RedisModule_UnblockClient)\n\n<span id=\"RedisModule_GetBlockedClientReadyKey\"></span>"
    },
    {
      "id": "redismodule-getblockedclientreadykey",
      "title": "`RedisModule_GetBlockedClientReadyKey`",
      "role": "content",
      "text": "RedisModuleString *RedisModule_GetBlockedClientReadyKey(RedisModuleCtx *ctx);\n\n**Available since:** 6.0.0\n\nGet the key that is ready when the reply callback is called in the context\nof a client blocked by [`RedisModule_BlockClientOnKeys()`](#RedisModule_BlockClientOnKeys).\n\n<span id=\"RedisModule_GetBlockedClientHandle\"></span>"
    },
    {
      "id": "redismodule-getblockedclienthandle",
      "title": "`RedisModule_GetBlockedClientHandle`",
      "role": "content",
      "text": "RedisModuleBlockedClient *RedisModule_GetBlockedClientHandle(RedisModuleCtx *ctx);\n\n**Available since:** 5.0.0\n\nGet the blocked client associated with a given context.\nThis is useful in the reply and timeout callbacks of blocked clients,\nbefore sometimes the module has the blocked client handle references\naround, and wants to cleanup it.\n\n<span id=\"RedisModule_BlockedClientDisconnected\"></span>"
    },
    {
      "id": "redismodule-blockedclientdisconnected",
      "title": "`RedisModule_BlockedClientDisconnected`",
      "role": "content",
      "text": "int RedisModule_BlockedClientDisconnected(RedisModuleCtx *ctx);\n\n**Available since:** 5.0.0\n\nReturn true if when the free callback of a blocked client is called,\nthe reason for the client to be unblocked is that it disconnected\nwhile it was blocked.\n\n<span id=\"section-thread-safe-contexts\"></span>"
    },
    {
      "id": "thread-safe-contexts",
      "title": "Thread Safe Contexts",
      "role": "content",
      "text": "<span id=\"RedisModule_GetThreadSafeContext\"></span>"
    },
    {
      "id": "redismodule-getthreadsafecontext",
      "title": "`RedisModule_GetThreadSafeContext`",
      "role": "content",
      "text": "RedisModuleCtx *RedisModule_GetThreadSafeContext(RedisModuleBlockedClient *bc);\n\n**Available since:** 4.0.0\n\nReturn a context which can be used inside threads to make Redis context\ncalls with certain modules APIs. If 'bc' is not NULL then the module will\nbe bound to a blocked client, and it will be possible to use the\n`RedisModule_Reply*` family of functions to accumulate a reply for when the\nclient will be unblocked. Otherwise the thread safe context will be\ndetached by a specific client.\n\nTo call non-reply APIs, the thread safe context must be prepared with:\n\n    RedisModule_ThreadSafeContextLock(ctx);\n    ... make your call here ...\n    RedisModule_ThreadSafeContextUnlock(ctx);\n\nThis is not needed when using `RedisModule_Reply*` functions, assuming\nthat a blocked client was used when the context was created, otherwise\nno `RedisModule_Reply`* call should be made at all.\n\nNOTE: If you're creating a detached thread safe context (bc is NULL),\nconsider using [`RedisModule_GetDetachedThreadSafeContext`](#RedisModule_GetDetachedThreadSafeContext) which will also retain\nthe module ID and thus be more useful for logging.\n\n<span id=\"RedisModule_GetDetachedThreadSafeContext\"></span>"
    },
    {
      "id": "redismodule-getdetachedthreadsafecontext",
      "title": "`RedisModule_GetDetachedThreadSafeContext`",
      "role": "content",
      "text": "RedisModuleCtx *RedisModule_GetDetachedThreadSafeContext(RedisModuleCtx *ctx);\n\n**Available since:** 6.0.9\n\nReturn a detached thread safe context that is not associated with any\nspecific blocked client, but is associated with the module's context.\n\nThis is useful for modules that wish to hold a global context over\na long term, for purposes such as logging.\n\n<span id=\"RedisModule_FreeThreadSafeContext\"></span>"
    },
    {
      "id": "redismodule-freethreadsafecontext",
      "title": "`RedisModule_FreeThreadSafeContext`",
      "role": "content",
      "text": "void RedisModule_FreeThreadSafeContext(RedisModuleCtx *ctx);\n\n**Available since:** 4.0.0\n\nRelease a thread safe context.\n\n<span id=\"RedisModule_ThreadSafeContextLock\"></span>"
    },
    {
      "id": "redismodule-threadsafecontextlock",
      "title": "`RedisModule_ThreadSafeContextLock`",
      "role": "content",
      "text": "void RedisModule_ThreadSafeContextLock(RedisModuleCtx *ctx);\n\n**Available since:** 4.0.0\n\nAcquire the server lock before executing a thread safe API call.\nThis is not needed for `RedisModule_Reply*` calls when there is\na blocked client connected to the thread safe context.\n\n<span id=\"RedisModule_ThreadSafeContextTryLock\"></span>"
    },
    {
      "id": "redismodule-threadsafecontexttrylock",
      "title": "`RedisModule_ThreadSafeContextTryLock`",
      "role": "content",
      "text": "int RedisModule_ThreadSafeContextTryLock(RedisModuleCtx *ctx);\n\n**Available since:** 6.0.8\n\nSimilar to [`RedisModule_ThreadSafeContextLock`](#RedisModule_ThreadSafeContextLock) but this function\nwould not block if the server lock is already acquired.\n\nIf successful (lock acquired) `REDISMODULE_OK` is returned,\notherwise `REDISMODULE_ERR` is returned and errno is set\naccordingly.\n\n<span id=\"RedisModule_ThreadSafeContextUnlock\"></span>"
    },
    {
      "id": "redismodule-threadsafecontextunlock",
      "title": "`RedisModule_ThreadSafeContextUnlock`",
      "role": "content",
      "text": "void RedisModule_ThreadSafeContextUnlock(RedisModuleCtx *ctx);\n\n**Available since:** 4.0.0\n\nRelease the server lock after a thread safe API call was executed.\n\n<span id=\"section-module-keyspace-notifications-api\"></span>"
    },
    {
      "id": "module-keyspace-notifications-api",
      "title": "Module Keyspace Notifications API",
      "role": "content",
      "text": "<span id=\"RedisModule_SubscribeToKeyspaceEvents\"></span>"
    },
    {
      "id": "redismodule-subscribetokeyspaceevents",
      "title": "`RedisModule_SubscribeToKeyspaceEvents`",
      "role": "content",
      "text": "int RedisModule_SubscribeToKeyspaceEvents(RedisModuleCtx *ctx,\n                                              int types,\n                                              RedisModuleNotificationFunc callback);\n\n**Available since:** 4.0.9\n\nSubscribe to keyspace notifications. This is a low-level version of the\nkeyspace-notifications API. A module can register callbacks to be notified\nwhen keyspace events occur.\n\nNotification events are filtered by their type (string events, set events,\netc), and the subscriber callback receives only events that match a specific\nmask of event types.\n\nWhen subscribing to notifications with [`RedisModule_SubscribeToKeyspaceEvents`](#RedisModule_SubscribeToKeyspaceEvents)\nthe module must provide an event type-mask, denoting the events the subscriber\nis interested in. This can be an ORed mask of any of the following flags:\n\n - `REDISMODULE_NOTIFY_GENERIC`: Generic commands like DEL, EXPIRE, RENAME\n - `REDISMODULE_NOTIFY_STRING`: String events\n - `REDISMODULE_NOTIFY_LIST`: List events\n - `REDISMODULE_NOTIFY_SET`: Set events\n - `REDISMODULE_NOTIFY_HASH`: Hash events\n - `REDISMODULE_NOTIFY_ZSET`: Sorted Set events\n - `REDISMODULE_NOTIFY_EXPIRED`: Expiration events\n - `REDISMODULE_NOTIFY_EVICTED`: Eviction events\n - `REDISMODULE_NOTIFY_STREAM`: Stream events\n - `REDISMODULE_NOTIFY_MODULE`: Module types events\n - `REDISMODULE_NOTIFY_KEYMISS`: Key-miss events\n                               Notice, key-miss event is the only type\n                               of event that is fired from within a read command.\n                               Performing RedisModule_Call with a write command from within\n                               this notification is wrong and discourage. It will\n                               cause the read command that trigger the event to be\n                               replicated to the AOF/Replica.\n\n - `REDISMODULE_NOTIFY_NEW`: New key notification\n - `REDISMODULE_NOTIFY_OVERWRITTEN`: Overwritten events\n - `REDISMODULE_NOTIFY_TYPE_CHANGED`: Type-changed events\n - `REDISMODULE_NOTIFY_KEY_TRIMMED`: Key trimmed events after a slot migration operation\n - `REDISMODULE_NOTIFY_ALL`: All events (Excluding `REDISMODULE_NOTIFY_KEYMISS`,\n                           REDISMODULE_NOTIFY_NEW, REDISMODULE_NOTIFY_OVERWRITTEN,\n                           REDISMODULE_NOTIFY_TYPE_CHANGED\n                           and REDISMODULE_NOTIFY_KEY_TRIMMED)\n - `REDISMODULE_NOTIFY_LOADED`: A special notification available only for modules,\n                              indicates that the key was loaded from persistence.\n                              Notice, when this event fires, the given key\n                              can not be retained, use RedisModule_CreateStringFromString\n                              instead.\n\nWe do not distinguish between key events and keyspace events, and it is up\nto the module to filter the actions taken based on the key.\n\nThe subscriber signature is:\n\n    int (*RedisModuleNotificationFunc) (RedisModuleCtx *ctx, int type,\n                                        const char *event,\n                                        RedisModuleString *key);\n\n`type` is the event type bit, that must match the mask given at registration\ntime. The event string is the actual command being executed, and key is the\nrelevant Redis key.\n\nNotification callback gets executed with a redis context that can not be\nused to send anything to the client, and has the db number where the event\noccurred as its selected db number.\n\nNotice that it is not necessary to enable notifications in redis.conf for\nmodule notifications to work.\n\nWarning: the notification callbacks are performed in a synchronous manner,\nso notification callbacks must to be fast, or they would slow Redis down.\nIf you need to take long actions, use threads to offload them.\n\nMoreover, the fact that the notification is executed synchronously means\nthat the notification code will be executed in the middle on Redis logic\n(commands logic, eviction, expire). Changing the key space while the logic\nruns is dangerous and discouraged. In order to react to key space events with\nwrite actions, please refer to [`RedisModule_AddPostNotificationJob`](#RedisModule_AddPostNotificationJob).\n\nSee [https://un5pn9hmggug.julianrbryant.com/docs/latest/develop/use/keyspace-notifications/](https://un5pn9hmggug.julianrbryant.com/docs/latest/develop/use/keyspace-notifications/) for more information.\n\n<span id=\"RedisModule_UnsubscribeFromKeyspaceEvents\"></span>"
    },
    {
      "id": "redismodule-unsubscribefromkeyspaceevents",
      "title": "`RedisModule_UnsubscribeFromKeyspaceEvents`",
      "role": "content",
      "text": "int RedisModule_UnsubscribeFromKeyspaceEvents(RedisModuleCtx *ctx,\n                                                  int types,\n                                                  RedisModuleNotificationFunc callback);\n\n**Available since:** 8.2.0\n\n\n[`RedisModule_UnsubscribeFromKeyspaceEvents`](#RedisModule_UnsubscribeFromKeyspaceEvents) - Unregister a module's callback from keyspace notifications for specific event types.\n\nThis function removes a previously registered subscription identified by both the event mask and the callback function.\nIt is useful to reduce performance overhead when the module no longer requires notifications for certain events.\n\nParameters:\n - ctx: The `RedisModuleCtx` associated with the calling module.\n - types: The event mask representing the keyspace notification types to unsubscribe from.\n - callback: The callback function pointer that was originally registered for these events.\n\nReturns:\n - `REDISMODULE_OK` on successful removal of the subscription.\n - `REDISMODULE_ERR` if no matching subscription was found or if invalid parameters were provided.\n\n<span id=\"RedisModule_AddPostNotificationJob\"></span>"
    },
    {
      "id": "redismodule-addpostnotificationjob",
      "title": "`RedisModule_AddPostNotificationJob`",
      "role": "content",
      "text": "int RedisModule_AddPostNotificationJob(RedisModuleCtx *ctx,\n                                           RedisModulePostNotificationJobFunc callback,\n                                           void *privdata,\n                                           void (*free_privdata)(void*));\n\n**Available since:** 7.2.0\n\nWhen running inside a key space notification callback, it is dangerous and highly discouraged to perform any write\noperation (See [`RedisModule_SubscribeToKeyspaceEvents`](#RedisModule_SubscribeToKeyspaceEvents)). In order to still perform write actions in this scenario,\nRedis provides [`RedisModule_AddPostNotificationJob`](#RedisModule_AddPostNotificationJob) API. The API allows to register a job callback which Redis will call\nwhen the following condition are promised to be fulfilled:\n1. It is safe to perform any write operation.\n2. The job will be called atomically along side the key space notification.\n\nNotice, one job might trigger key space notifications that will trigger more jobs.\nThis raises a concerns of entering an infinite loops, we consider infinite loops\nas a logical bug that need to be fixed in the module, an attempt to protect against\ninfinite loops by halting the execution could result in violation of the feature correctness\nand so Redis will make no attempt to protect the module from infinite loops.\n\n'`free_pd`' can be NULL and in such case will not be used.\n\nReturn `REDISMODULE_OK` on success and `REDISMODULE_ERR` if was called while loading data from disk (AOF or RDB) or\nif the instance is a readonly replica.\n\n<span id=\"RedisModule_GetNotifyKeyspaceEvents\"></span>"
    },
    {
      "id": "redismodule-getnotifykeyspaceevents",
      "title": "`RedisModule_GetNotifyKeyspaceEvents`",
      "role": "content",
      "text": "int RedisModule_GetNotifyKeyspaceEvents(void);\n\n**Available since:** 6.0.0\n\nGet the configured bitmap of notify-keyspace-events (Could be used\nfor additional filtering in `RedisModuleNotificationFunc`)\n\n<span id=\"RedisModule_NotifyKeyspaceEvent\"></span>"
    },
    {
      "id": "redismodule-notifykeyspaceevent",
      "title": "`RedisModule_NotifyKeyspaceEvent`",
      "role": "content",
      "text": "int RedisModule_NotifyKeyspaceEvent(RedisModuleCtx *ctx,\n                                        int type,\n                                        const char *event,\n                                        RedisModuleString *key);\n\n**Available since:** 6.0.0\n\nExpose notifyKeyspaceEvent to modules\n\n<span id=\"section-modules-cluster-api\"></span>"
    },
    {
      "id": "modules-cluster-api",
      "title": "Modules Cluster API",
      "role": "content",
      "text": "<span id=\"RedisModule_RegisterClusterMessageReceiver\"></span>"
    },
    {
      "id": "redismodule-registerclustermessagereceiver",
      "title": "`RedisModule_RegisterClusterMessageReceiver`",
      "role": "content",
      "text": "void RedisModule_RegisterClusterMessageReceiver(RedisModuleCtx *ctx,\n                                                    uint8_t type,\n                                                    RedisModuleClusterMessageReceiver callback);\n\n**Available since:** 5.0.0\n\nRegister a callback receiver for cluster messages of type 'type'. If there\nwas already a registered callback, this will replace the callback function\nwith the one provided, otherwise if the callback is set to NULL and there\nis already a callback for this function, the callback is unregistered\n(so this API call is also used in order to delete the receiver).\n\n<span id=\"RedisModule_SendClusterMessage\"></span>"
    },
    {
      "id": "redismodule-sendclustermessage",
      "title": "`RedisModule_SendClusterMessage`",
      "role": "content",
      "text": "int RedisModule_SendClusterMessage(RedisModuleCtx *ctx,\n                                       const char *target_id,\n                                       uint8_t type,\n                                       const char *msg,\n                                       uint32_t len);\n\n**Available since:** 5.0.0\n\nSend a message to all the nodes in the cluster if `target` is NULL, otherwise\nat the specified target, which is a `REDISMODULE_NODE_ID_LEN` bytes node ID, as\nreturned by the receiver callback or by the nodes iteration functions.\n\nThe function returns `REDISMODULE_OK` if the message was successfully sent,\notherwise if the node is not connected or such node ID does not map to any\nknown cluster node, `REDISMODULE_ERR` is returned.\n\n<span id=\"RedisModule_GetClusterNodesList\"></span>"
    },
    {
      "id": "redismodule-getclusternodeslist",
      "title": "`RedisModule_GetClusterNodesList`",
      "role": "content",
      "text": "char **RedisModule_GetClusterNodesList(RedisModuleCtx *ctx, size_t *numnodes);\n\n**Available since:** 5.0.0\n\nReturn an array of string pointers, each string pointer points to a cluster\nnode ID of exactly `REDISMODULE_NODE_ID_LEN` bytes (without any null term).\nThe number of returned node IDs is stored into `*numnodes`.\nHowever if this function is called by a module not running an a Redis\ninstance with Redis Cluster enabled, NULL is returned instead.\n\nThe IDs returned can be used with [`RedisModule_GetClusterNodeInfo()`](#RedisModule_GetClusterNodeInfo) in order\nto get more information about single node.\n\nThe array returned by this function must be freed using the function\n[`RedisModule_FreeClusterNodesList()`](#RedisModule_FreeClusterNodesList).\n\nExample:\n\n    size_t count, j;\n    char **ids = RedisModule_GetClusterNodesList(ctx,&count);\n    for (j = 0; j < count; j++) {\n        RedisModule_Log(ctx,\"notice\",\"Node %.*s\",\n            REDISMODULE_NODE_ID_LEN,ids[j]);\n    }\n    RedisModule_FreeClusterNodesList(ids);\n\n<span id=\"RedisModule_FreeClusterNodesList\"></span>"
    },
    {
      "id": "redismodule-freeclusternodeslist",
      "title": "`RedisModule_FreeClusterNodesList`",
      "role": "content",
      "text": "void RedisModule_FreeClusterNodesList(char **ids);\n\n**Available since:** 5.0.0\n\nFree the node list obtained with [`RedisModule_GetClusterNodesList`](#RedisModule_GetClusterNodesList).\n\n<span id=\"RedisModule_GetMyClusterID\"></span>"
    },
    {
      "id": "redismodule-getmyclusterid",
      "title": "`RedisModule_GetMyClusterID`",
      "role": "content",
      "text": "const char *RedisModule_GetMyClusterID(void);\n\n**Available since:** 5.0.0\n\nReturn this node ID (`REDISMODULE_CLUSTER_ID_LEN` bytes) or NULL if the cluster\nis disabled.\n\n<span id=\"RedisModule_GetClusterSize\"></span>"
    },
    {
      "id": "redismodule-getclustersize",
      "title": "`RedisModule_GetClusterSize`",
      "role": "content",
      "text": "size_t RedisModule_GetClusterSize(void);\n\n**Available since:** 5.0.0\n\nReturn the number of nodes in the cluster, regardless of their state\n(handshake, noaddress, ...) so that the number of active nodes may actually\nbe smaller, but not greater than this number. If the instance is not in\ncluster mode, zero is returned.\n\n<span id=\"RedisModule_GetClusterNodeInfo\"></span>"
    },
    {
      "id": "redismodule-getclusternodeinfo",
      "title": "`RedisModule_GetClusterNodeInfo`",
      "role": "content",
      "text": "int RedisModule_GetClusterNodeInfo(RedisModuleCtx *ctx,\n                                       const char *id,\n                                       char *ip,\n                                       char *master_id,\n                                       int *port,\n                                       int *flags);\n\n**Available since:** 5.0.0\n\nPopulate the specified info for the node having as ID the specified 'id',\nthen returns `REDISMODULE_OK`. Otherwise if the format of node ID is invalid\nor the node ID does not exist from the POV of this local node, `REDISMODULE_ERR`\nis returned.\n\nThe arguments `ip`, `master_id`, `port` and `flags` can be NULL in case we don't\nneed to populate back certain info. If an `ip` and `master_id` (only populated\nif the instance is a slave) are specified, they point to buffers holding\nat least `REDISMODULE_NODE_ID_LEN` bytes. The strings written back as `ip`\nand `master_id` are not null terminated.\n\nThe list of flags reported is the following:\n\n* `REDISMODULE_NODE_MYSELF`:       This node\n* `REDISMODULE_NODE_MASTER`:       The node is a master\n* `REDISMODULE_NODE_SLAVE`:        The node is a replica\n* `REDISMODULE_NODE_PFAIL`:        We see the node as failing\n* `REDISMODULE_NODE_FAIL`:         The cluster agrees the node is failing\n* `REDISMODULE_NODE_NOFAILOVER`:   The slave is configured to never failover\n\n<span id=\"RedisModule_SetClusterFlags\"></span>"
    },
    {
      "id": "redismodule-setclusterflags",
      "title": "`RedisModule_SetClusterFlags`",
      "role": "content",
      "text": "void RedisModule_SetClusterFlags(RedisModuleCtx *ctx, uint64_t flags);\n\n**Available since:** 5.0.0\n\nSet Redis Cluster flags in order to change the normal behavior of\nRedis Cluster, especially with the goal of disabling certain functions.\nThis is useful for modules that use the Cluster API in order to create\na different distributed system, but still want to use the Redis Cluster\nmessage bus. Flags that can be set:\n\n* `CLUSTER_MODULE_FLAG_NO_FAILOVER`\n* `CLUSTER_MODULE_FLAG_NO_REDIRECTION`\n\nWith the following effects:\n\n* `NO_FAILOVER`: prevent Redis Cluster slaves from failing over a dead master.\n               Also disables the replica migration feature.\n\n* `NO_REDIRECTION`: Every node will accept any key, without trying to perform\n                  partitioning according to the Redis Cluster algorithm.\n                  Slots information will still be propagated across the\n                  cluster, but without effect.\n\n<span id=\"RedisModule_ClusterDisableTrim\"></span>"
    },
    {
      "id": "redismodule-clusterdisabletrim",
      "title": "`RedisModule_ClusterDisableTrim`",
      "role": "content",
      "text": "int RedisModule_ClusterDisableTrim(RedisModuleCtx *ctx);\n\n**Available since:** 8.4.1\n\n[`RedisModule_ClusterDisableTrim`](#RedisModule_ClusterDisableTrim) allows a module to temporarily prevent slot trimming\nafter a slot migration. This is useful when the module has asynchronous\noperations that rely on keys in migrating slots, which would be trimmed.\n\nThe module must call [`RedisModule_ClusterEnableTrim`](#RedisModule_ClusterEnableTrim) once it has completed those\noperations to re-enable trimming.\n\nTrimming uses a reference counter: every call to [`RedisModule_ClusterDisableTrim`](#RedisModule_ClusterDisableTrim)\nincrements the counter, and every [`RedisModule_ClusterEnableTrim`](#RedisModule_ClusterEnableTrim) call decrements it.\nTrimming remains disabled as long as the counter is greater than zero.\n\nDisable automatic slot trimming.\n\n<span id=\"RedisModule_ClusterEnableTrim\"></span>"
    },
    {
      "id": "redismodule-clusterenabletrim",
      "title": "`RedisModule_ClusterEnableTrim`",
      "role": "content",
      "text": "int RedisModule_ClusterEnableTrim(RedisModuleCtx *ctx);\n\n**Available since:** 8.4.1\n\nEnable automatic slot trimming. See also comments on [`RedisModule_ClusterDisableTrim`](#RedisModule_ClusterDisableTrim).\n\n<span id=\"RedisModule_ClusterKeySlot\"></span>"
    },
    {
      "id": "redismodule-clusterkeyslot",
      "title": "`RedisModule_ClusterKeySlot`",
      "role": "content",
      "text": "unsigned int RedisModule_ClusterKeySlot(RedisModuleString *key);\n\n**Available since:** 7.4.0\n\nReturns the cluster slot of a key, similar to the `CLUSTER KEYSLOT` command.\nThis function works even if cluster mode is not enabled.\n\n<span id=\"RedisModule_ClusterKeySlotC\"></span>"
    },
    {
      "id": "redismodule-clusterkeyslotc",
      "title": "`RedisModule_ClusterKeySlotC`",
      "role": "content",
      "text": "unsigned int RedisModule_ClusterKeySlotC(const char *keystr, size_t keylen);\n\n**Available since:** 8.4.0\n\nLike [`RedisModule_ClusterKeySlot`](#RedisModule_ClusterKeySlot), but gets a char pointer and a length.\nReturns the cluster slot of a key, similar to the `CLUSTER KEYSLOT` command.\nThis function works even if cluster mode is not enabled.\n\n<span id=\"RedisModule_ClusterCanonicalKeyNameInSlot\"></span>"
    },
    {
      "id": "redismodule-clustercanonicalkeynameinslot",
      "title": "`RedisModule_ClusterCanonicalKeyNameInSlot`",
      "role": "content",
      "text": "const char *RedisModule_ClusterCanonicalKeyNameInSlot(unsigned int slot);\n\n**Available since:** 7.4.0\n\nReturns a short string that can be used as a key or as a hash tag in a key,\nsuch that the key maps to the given cluster slot. Returns NULL if slot is not\na valid slot.\n\n<span id=\"RedisModule_ClusterCanAccessKeysInSlot\"></span>"
    },
    {
      "id": "redismodule-clustercanaccesskeysinslot",
      "title": "`RedisModule_ClusterCanAccessKeysInSlot`",
      "role": "content",
      "text": "int RedisModule_ClusterCanAccessKeysInSlot(int slot);\n\n**Available since:** 8.4.0\n\nReturns 1 if keys in the specified slot can be accessed by this node, 0 otherwise.\n\nThis function returns 1 in the following cases:\n- The slot is owned by this node or by its master if this node is a replica\n- The slot is being imported under the old slot migration approach (CLUSTER SETSLOT <slot> IMPORTING ..)\n- Not in cluster mode (all slots are accessible)\n\nReturns 0 for:\n- Invalid slot numbers (< 0 or >= 16384)\n- Slots owned by other nodes\n\n<span id=\"RedisModule_ClusterPropagateForSlotMigration\"></span>"
    },
    {
      "id": "redismodule-clusterpropagateforslotmigration",
      "title": "`RedisModule_ClusterPropagateForSlotMigration`",
      "role": "content",
      "text": "int RedisModule_ClusterPropagateForSlotMigration(RedisModuleCtx *ctx,\n                                                     const char *cmdname,\n                                                     const char *fmt,\n                                                     ...);\n\n**Available since:** 8.4.0\n\nPropagate commands along with slot migration.\n\nThis function allows modules to add commands that will be sent to the\ndestination node before the actual slot migration begins. It should only be\ncalled during the `REDISMODULE_SUBEVENT_CLUSTER_SLOT_MIGRATION_MIGRATE_MODULE_PROPAGATE` event.\n\nThis function can be called multiple times within the same event to\nreplicate multiple commands. All commands will be sent before the\nactual slot data migration begins.\n\nNote: This function is only available in the fork child process just before\n      slot snapshot delivery begins.\n\nOn success `REDISMODULE_OK` is returned, otherwise\n`REDISMODULE_ERR` is returned and errno is set to the following values:\n\n* EINVAL: function arguments or format specifiers are invalid.\n* EBADF: not called in the correct context, e.g. not called in the `REDISMODULE_SUBEVENT_CLUSTER_SLOT_MIGRATION_MIGRATE_MODULE_PROPAGATE` event.\n* ENOENT: command does not exist.\n* ENOTSUP: command is cross-slot.\n* ERANGE: command contains keys that are not within the migrating slot range.\n\n<span id=\"RedisModule_ClusterGetLocalSlotRanges\"></span>"
    },
    {
      "id": "redismodule-clustergetlocalslotranges",
      "title": "`RedisModule_ClusterGetLocalSlotRanges`",
      "role": "content",
      "text": "RedisModuleSlotRangeArray *RedisModule_ClusterGetLocalSlotRanges(RedisModuleCtx *ctx);\n\n**Available since:** 8.4.0\n\nReturns the locally owned slot ranges for the node.\n\nAn optional `ctx` can be provided to enable auto-memory management.\nIf cluster mode is disabled, the array will include all slots (0–16383).\nIf the node is a replica, the slot ranges of its master are returned.\n\nThe returned array must be freed with [`RedisModule_ClusterFreeSlotRanges()`](#RedisModule_ClusterFreeSlotRanges).\n\n<span id=\"RedisModule_ClusterFreeSlotRanges\"></span>"
    },
    {
      "id": "redismodule-clusterfreeslotranges",
      "title": "`RedisModule_ClusterFreeSlotRanges`",
      "role": "content",
      "text": "void RedisModule_ClusterFreeSlotRanges(RedisModuleCtx *ctx,\n                                           RedisModuleSlotRangeArray *slots);\n\n**Available since:** 8.4.0\n\nFrees a slot range array returned by [`RedisModule_ClusterGetLocalSlotRanges()`](#RedisModule_ClusterGetLocalSlotRanges).\nPass the `ctx` pointer only if the array was created with a context.\n\n<span id=\"section-modules-timers-api\"></span>"
    },
    {
      "id": "modules-timers-api",
      "title": "Modules Timers API",
      "role": "content",
      "text": "Module timers are a high precision \"green timers\" abstraction where\nevery module can register even millions of timers without problems, even if\nthe actual event loop will just have a single timer that is used to awake the\nmodule timers subsystem in order to process the next event.\n\nAll the timers are stored into a radix tree, ordered by expire time, when\nthe main Redis event loop timer callback is called, we try to process all\nthe timers already expired one after the other. Then we re-enter the event\nloop registering a timer that will expire when the next to process module\ntimer will expire.\n\nEvery time the list of active timers drops to zero, we unregister the\nmain event loop timer, so that there is no overhead when such feature is\nnot used.\n\n<span id=\"RedisModule_CreateTimer\"></span>"
    },
    {
      "id": "redismodule-createtimer",
      "title": "`RedisModule_CreateTimer`",
      "role": "content",
      "text": "RedisModuleTimerID RedisModule_CreateTimer(RedisModuleCtx *ctx,\n                                               mstime_t period,\n                                               RedisModuleTimerProc callback,\n                                               void *data);\n\n**Available since:** 5.0.0\n\nCreate a new timer that will fire after `period` milliseconds, and will call\nthe specified function using `data` as argument. The returned timer ID can be\nused to get information from the timer or to stop it before it fires.\nNote that for the common use case of a repeating timer (Re-registration\nof the timer inside the `RedisModuleTimerProc` callback) it matters when\nthis API is called:\nIf it is called at the beginning of 'callback' it means\nthe event will triggered every 'period'.\nIf it is called at the end of 'callback' it means\nthere will 'period' milliseconds gaps between events.\n(If the time it takes to execute 'callback' is negligible the two\nstatements above mean the same)\n\n<span id=\"RedisModule_StopTimer\"></span>"
    },
    {
      "id": "redismodule-stoptimer",
      "title": "`RedisModule_StopTimer`",
      "role": "content",
      "text": "int RedisModule_StopTimer(RedisModuleCtx *ctx,\n                              RedisModuleTimerID id,\n                              void **data);\n\n**Available since:** 5.0.0\n\nStop a timer, returns `REDISMODULE_OK` if the timer was found, belonged to the\ncalling module, and was stopped, otherwise `REDISMODULE_ERR` is returned.\nIf not NULL, the data pointer is set to the value of the data argument when\nthe timer was created.\n\n<span id=\"RedisModule_GetTimerInfo\"></span>"
    },
    {
      "id": "redismodule-gettimerinfo",
      "title": "`RedisModule_GetTimerInfo`",
      "role": "content",
      "text": "int RedisModule_GetTimerInfo(RedisModuleCtx *ctx,\n                                 RedisModuleTimerID id,\n                                 uint64_t *remaining,\n                                 void **data);\n\n**Available since:** 5.0.0\n\nObtain information about a timer: its remaining time before firing\n(in milliseconds), and the private data pointer associated with the timer.\nIf the timer specified does not exist or belongs to a different module\nno information is returned and the function returns `REDISMODULE_ERR`, otherwise\n`REDISMODULE_OK` is returned. The arguments remaining or data can be NULL if\nthe caller does not need certain information.\n\n<span id=\"section-modules-eventloop-api\"></span>"
    },
    {
      "id": "modules-eventloop-api",
      "title": "Modules EventLoop API",
      "role": "content",
      "text": "<span id=\"RedisModule_EventLoopAdd\"></span>"
    },
    {
      "id": "redismodule-eventloopadd",
      "title": "`RedisModule_EventLoopAdd`",
      "role": "content",
      "text": "int RedisModule_EventLoopAdd(int fd,\n                                 int mask,\n                                 RedisModuleEventLoopFunc func,\n                                 void *user_data);\n\n**Available since:** 7.0.0\n\nAdd a pipe / socket event to the event loop.\n\n* `mask` must be one of the following values:\n\n    * `REDISMODULE_EVENTLOOP_READABLE`\n    * `REDISMODULE_EVENTLOOP_WRITABLE`\n    * `REDISMODULE_EVENTLOOP_READABLE | REDISMODULE_EVENTLOOP_WRITABLE`\n\nOn success `REDISMODULE_OK` is returned, otherwise\n`REDISMODULE_ERR` is returned and errno is set to the following values:\n\n* ERANGE: `fd` is negative or higher than `maxclients` Redis config.\n* EINVAL: `callback` is NULL or `mask` value is invalid.\n\n`errno` might take other values in case of an internal error.\n\nExample:\n\n    void onReadable(int fd, void *user_data, int mask) {\n        char buf[32];\n        int bytes = read(fd,buf,sizeof(buf));\n        printf(\"Read %d bytes \\n\", bytes);\n    }\n    RedisModule_EventLoopAdd(fd, REDISMODULE_EVENTLOOP_READABLE, onReadable, NULL);\n\n<span id=\"RedisModule_EventLoopDel\"></span>"
    },
    {
      "id": "redismodule-eventloopdel",
      "title": "`RedisModule_EventLoopDel`",
      "role": "content",
      "text": "int RedisModule_EventLoopDel(int fd, int mask);\n\n**Available since:** 7.0.0\n\nDelete a pipe / socket event from the event loop.\n\n* `mask` must be one of the following values:\n\n    * `REDISMODULE_EVENTLOOP_READABLE`\n    * `REDISMODULE_EVENTLOOP_WRITABLE`\n    * `REDISMODULE_EVENTLOOP_READABLE | REDISMODULE_EVENTLOOP_WRITABLE`\n\nOn success `REDISMODULE_OK` is returned, otherwise\n`REDISMODULE_ERR` is returned and errno is set to the following values:\n\n* ERANGE: `fd` is negative or higher than `maxclients` Redis config.\n* EINVAL: `mask` value is invalid.\n\n<span id=\"RedisModule_EventLoopAddOneShot\"></span>"
    },
    {
      "id": "redismodule-eventloopaddoneshot",
      "title": "`RedisModule_EventLoopAddOneShot`",
      "role": "content",
      "text": "int RedisModule_EventLoopAddOneShot(RedisModuleEventLoopOneShotFunc func,\n                                        void *user_data);\n\n**Available since:** 7.0.0\n\nThis function can be called from other threads to trigger callback on Redis\nmain thread. On success `REDISMODULE_OK` is returned. If `func` is NULL\n`REDISMODULE_ERR` is returned and errno is set to EINVAL.\n\n<span id=\"section-modules-acl-api\"></span>"
    },
    {
      "id": "modules-acl-api",
      "title": "Modules ACL API",
      "role": "content",
      "text": "Implements a hook into the authentication and authorization within Redis.\n\n<span id=\"RedisModule_CreateModuleUser\"></span>"
    },
    {
      "id": "redismodule-createmoduleuser",
      "title": "`RedisModule_CreateModuleUser`",
      "role": "content",
      "text": "RedisModuleUser *RedisModule_CreateModuleUser(const char *name);\n\n**Available since:** 6.0.0\n\nCreates a Redis ACL user that the module can use to authenticate a client.\nAfter obtaining the user, the module should set what such user can do\nusing the `RedisModule_SetUserACL()` function. Once configured, the user\ncan be used in order to authenticate a connection, with the specified\nACL rules, using the `RedisModule_AuthClientWithUser()` function.\n\nNote that:\n\n* Users created here are not listed by the ACL command.\n* Users created here are not checked for duplicated name, so it's up to\n  the module calling this function to take care of not creating users\n  with the same name.\n* The created user can be used to authenticate multiple Redis connections.\n\nThe caller can later free the user using the function\n[`RedisModule_FreeModuleUser()`](#RedisModule_FreeModuleUser). When this function is called, if there are\nstill clients authenticated with this user, they are disconnected.\nThe function to free the user should only be used when the caller really\nwants to invalidate the user to define a new one with different\ncapabilities.\n\n<span id=\"RedisModule_FreeModuleUser\"></span>"
    },
    {
      "id": "redismodule-freemoduleuser",
      "title": "`RedisModule_FreeModuleUser`",
      "role": "content",
      "text": "int RedisModule_FreeModuleUser(RedisModuleUser *user);\n\n**Available since:** 6.0.0\n\nFrees a given user and disconnects all of the clients that have been\nauthenticated with it. See [`RedisModule_CreateModuleUser`](#RedisModule_CreateModuleUser) for detailed usage.\n\n<span id=\"RedisModule_SetModuleUserACL\"></span>"
    },
    {
      "id": "redismodule-setmoduleuseracl",
      "title": "`RedisModule_SetModuleUserACL`",
      "role": "content",
      "text": "int RedisModule_SetModuleUserACL(RedisModuleUser *user, const char* acl);\n\n**Available since:** 6.0.0\n\nSets the permissions of a user created through the redis module\ninterface. The syntax is the same as ACL SETUSER, so refer to the\ndocumentation in acl.c for more information. See [`RedisModule_CreateModuleUser`](#RedisModule_CreateModuleUser)\nfor detailed usage.\n\nReturns `REDISMODULE_OK` on success and `REDISMODULE_ERR` on failure\nand will set an errno describing why the operation failed.\n\n<span id=\"RedisModule_SetModuleUserACLString\"></span>"
    },
    {
      "id": "redismodule-setmoduleuseraclstring",
      "title": "`RedisModule_SetModuleUserACLString`",
      "role": "content",
      "text": "int RedisModule_SetModuleUserACLString(RedisModuleCtx *ctx,\n                                           RedisModuleUser *user,\n                                           const char *acl,\n                                           RedisModuleString **error);\n\n**Available since:** 7.0.6\n\nSets the permission of a user with a complete ACL string, such as one\nwould use on the redis ACL SETUSER command line API. This differs from\n[`RedisModule_SetModuleUserACL`](#RedisModule_SetModuleUserACL), which only takes single ACL operations at a time.\n\nReturns `REDISMODULE_OK` on success and `REDISMODULE_ERR` on failure\nif a `RedisModuleString` is provided in error, a string describing the error\nwill be returned\n\n<span id=\"RedisModule_GetModuleUserACLString\"></span>"
    },
    {
      "id": "redismodule-getmoduleuseraclstring",
      "title": "`RedisModule_GetModuleUserACLString`",
      "role": "content",
      "text": "RedisModuleString *RedisModule_GetModuleUserACLString(RedisModuleUser *user);\n\n**Available since:** 7.0.6\n\nGet the ACL string for a given user\nReturns a `RedisModuleString`\n\n<span id=\"RedisModule_GetCurrentUserName\"></span>"
    },
    {
      "id": "redismodule-getcurrentusername",
      "title": "`RedisModule_GetCurrentUserName`",
      "role": "content",
      "text": "RedisModuleString *RedisModule_GetCurrentUserName(RedisModuleCtx *ctx);\n\n**Available since:** 7.0.0\n\nRetrieve the user name of the client connection behind the current context.\nThe user name can be used later, in order to get a `RedisModuleUser`.\nSee more information in [`RedisModule_GetModuleUserFromUserName`](#RedisModule_GetModuleUserFromUserName).\n\nThe returned string must be released with [`RedisModule_FreeString()`](#RedisModule_FreeString) or by\nenabling automatic memory management.\n\n<span id=\"RedisModule_GetModuleUserFromUserName\"></span>"
    },
    {
      "id": "redismodule-getmoduleuserfromusername",
      "title": "`RedisModule_GetModuleUserFromUserName`",
      "role": "content",
      "text": "RedisModuleUser *RedisModule_GetModuleUserFromUserName(RedisModuleString *name);\n\n**Available since:** 7.0.0\n\nA `RedisModuleUser` can be used to check if command, key or channel can be executed or\naccessed according to the ACLs rules associated with that user.\nWhen a Module wants to do ACL checks on a general ACL user (not created by [`RedisModule_CreateModuleUser`](#RedisModule_CreateModuleUser)),\nit can get the `RedisModuleUser` from this API, based on the user name retrieved by [`RedisModule_GetCurrentUserName`](#RedisModule_GetCurrentUserName).\n\nSince a general ACL user can be deleted at any time, this `RedisModuleUser` should be used only in the context\nwhere this function was called. In order to do ACL checks out of that context, the Module can store the user name,\nand call this API at any other context.\n\nReturns NULL if the user is disabled or the user does not exist.\nThe caller should later free the user using the function [`RedisModule_FreeModuleUser()`](#RedisModule_FreeModuleUser).\n\n<span id=\"RedisModule_ACLCheckCommandPermissions\"></span>"
    },
    {
      "id": "redismodule-aclcheckcommandpermissions",
      "title": "`RedisModule_ACLCheckCommandPermissions`",
      "role": "content",
      "text": "int RedisModule_ACLCheckCommandPermissions(RedisModuleUser *user,\n                                               RedisModuleString **argv,\n                                               int argc);\n\n**Available since:** 7.0.0\n\nChecks if the command can be executed by the user, according to the ACLs associated with it.\n\nOn success a `REDISMODULE_OK` is returned, otherwise\n`REDISMODULE_ERR` is returned and errno is set to the following values:\n\n* ENOENT: Specified command does not exist.\n* EACCES: Command cannot be executed, according to ACL rules\n\n<span id=\"RedisModule_ACLCheckKeyPermissions\"></span>"
    },
    {
      "id": "redismodule-aclcheckkeypermissions",
      "title": "`RedisModule_ACLCheckKeyPermissions`",
      "role": "content",
      "text": "int RedisModule_ACLCheckKeyPermissions(RedisModuleUser *user,\n                                           RedisModuleString *key,\n                                           int flags);\n\n**Available since:** 7.0.0\n\nCheck if the key can be accessed by the user according to the ACLs attached to the user\nand the flags representing the key access. The flags are the same that are used in the\nkeyspec for logical operations. These flags are documented in [`RedisModule_SetCommandInfo`](#RedisModule_SetCommandInfo) as\nthe `REDISMODULE_CMD_KEY_ACCESS`, `REDISMODULE_CMD_KEY_UPDATE`, `REDISMODULE_CMD_KEY_INSERT`,\nand `REDISMODULE_CMD_KEY_DELETE` flags.\n\nIf no flags are supplied, the user is still required to have some access to the key for\nthis command to return successfully.\n\nIf the user is able to access the key then `REDISMODULE_OK` is returned, otherwise\n`REDISMODULE_ERR` is returned and errno is set to one of the following values:\n\n* EINVAL: The provided flags are invalid.\n* EACCESS: The user does not have permission to access the key.\n\n<span id=\"RedisModule_ACLCheckKeyPrefixPermissions\"></span>"
    },
    {
      "id": "redismodule-aclcheckkeyprefixpermissions",
      "title": "`RedisModule_ACLCheckKeyPrefixPermissions`",
      "role": "content",
      "text": "int RedisModule_ACLCheckKeyPrefixPermissions(RedisModuleUser *user,\n                                                 RedisModuleString *prefix,\n                                                 int flags);\n\n**Available since:** 8.0.0\n\nCheck if the user can access keys matching the given key prefix according to the ACLs \nattached to the user and the flags representing key access. The flags are the same that \nare used in the keyspec for logical operations. These flags are documented in \n[`RedisModule_SetCommandInfo`](#RedisModule_SetCommandInfo) as the `REDISMODULE_CMD_KEY_ACCESS`, \n`REDISMODULE_CMD_KEY_UPDATE`, `REDISMODULE_CMD_KEY_INSERT`, and `REDISMODULE_CMD_KEY_DELETE` flags.\n\nIf no flags are supplied, the user is still required to have some access to keys matching \nthe prefix for this command to return successfully.\n\nIf the user is able to access keys matching the prefix, then `REDISMODULE_OK` is returned.\nOtherwise, `REDISMODULE_ERR` is returned and errno is set to one of the following values:\n\n* EINVAL: The provided flags are invalid.\n* EACCES: The user does not have permission to access keys matching the prefix.\n\n<span id=\"RedisModule_ACLCheckChannelPermissions\"></span>"
    },
    {
      "id": "redismodule-aclcheckchannelpermissions",
      "title": "`RedisModule_ACLCheckChannelPermissions`",
      "role": "content",
      "text": "int RedisModule_ACLCheckChannelPermissions(RedisModuleUser *user,\n                                               RedisModuleString *ch,\n                                               int flags);\n\n**Available since:** 7.0.0\n\nCheck if the pubsub channel can be accessed by the user based off of the given\naccess flags. See [`RedisModule_ChannelAtPosWithFlags`](#RedisModule_ChannelAtPosWithFlags) for more information about the\npossible flags that can be passed in.\n\nIf the user is able to access the pubsub channel then `REDISMODULE_OK` is returned, otherwise\n`REDISMODULE_ERR` is returned and errno is set to one of the following values:\n\n* EINVAL: The provided flags are invalid.\n* EACCESS: The user does not have permission to access the pubsub channel.\n\n<span id=\"RedisModule_ACLAddLogEntry\"></span>"
    },
    {
      "id": "redismodule-acladdlogentry",
      "title": "`RedisModule_ACLAddLogEntry`",
      "role": "content",
      "text": "int RedisModule_ACLAddLogEntry(RedisModuleCtx *ctx,\n                                   RedisModuleUser *user,\n                                   RedisModuleString *object,\n                                   RedisModuleACLLogEntryReason reason);\n\n**Available since:** 7.0.0\n\nAdds a new entry in the ACL log.\nReturns `REDISMODULE_OK` on success and `REDISMODULE_ERR` on error.\n\nFor more information about ACL log, please refer to [https://un5pn9hmggug.julianrbryant.com/commands/acl-log](https://un5pn9hmggug.julianrbryant.com/commands/acl-log)\n\n<span id=\"RedisModule_ACLAddLogEntryByUserName\"></span>"
    },
    {
      "id": "redismodule-acladdlogentrybyusername",
      "title": "`RedisModule_ACLAddLogEntryByUserName`",
      "role": "content",
      "text": "int RedisModule_ACLAddLogEntryByUserName(RedisModuleCtx *ctx,\n                                             RedisModuleString *username,\n                                             RedisModuleString *object,\n                                             RedisModuleACLLogEntryReason reason);\n\n**Available since:** 7.2.0\n\nAdds a new entry in the ACL log with the `username` `RedisModuleString` provided.\nReturns `REDISMODULE_OK` on success and `REDISMODULE_ERR` on error.\n\nFor more information about ACL log, please refer to [https://un5pn9hmggug.julianrbryant.com/commands/acl-log](https://un5pn9hmggug.julianrbryant.com/commands/acl-log)\n\n<span id=\"RedisModule_AuthenticateClientWithUser\"></span>"
    },
    {
      "id": "redismodule-authenticateclientwithuser",
      "title": "`RedisModule_AuthenticateClientWithUser`",
      "role": "content",
      "text": "int RedisModule_AuthenticateClientWithUser(RedisModuleCtx *ctx,\n                                               RedisModuleUser *module_user,\n                                               RedisModuleUserChangedFunc callback,\n                                               void *privdata,\n                                               uint64_t *client_id);\n\n**Available since:** 6.0.0\n\nAuthenticate the current context's user with the provided redis acl user.\nReturns `REDISMODULE_ERR` if the user is disabled.\n\nSee authenticateClientWithUser for information about callback, `client_id`,\nand general usage for authentication.\n\n<span id=\"RedisModule_AuthenticateClientWithACLUser\"></span>"
    },
    {
      "id": "redismodule-authenticateclientwithacluser",
      "title": "`RedisModule_AuthenticateClientWithACLUser`",
      "role": "content",
      "text": "int RedisModule_AuthenticateClientWithACLUser(RedisModuleCtx *ctx,\n                                                  const char *name,\n                                                  size_t len,\n                                                  RedisModuleUserChangedFunc callback,\n                                                  void *privdata,\n                                                  uint64_t *client_id);\n\n**Available since:** 6.0.0\n\nAuthenticate the current context's user with the provided redis acl user.\nReturns `REDISMODULE_ERR` if the user is disabled or the user does not exist.\n\nSee authenticateClientWithUser for information about callback, `client_id`,\nand general usage for authentication.\n\n<span id=\"RedisModule_DeauthenticateAndCloseClient\"></span>"
    },
    {
      "id": "redismodule-deauthenticateandcloseclient",
      "title": "`RedisModule_DeauthenticateAndCloseClient`",
      "role": "content",
      "text": "int RedisModule_DeauthenticateAndCloseClient(RedisModuleCtx *ctx,\n                                                 uint64_t client_id);\n\n**Available since:** 6.0.0\n\nDeauthenticate and close the client. The client resources will not be\nimmediately freed, but will be cleaned up in a background job. This is\nthe recommended way to deauthenticate a client since most clients can't\nhandle users becoming deauthenticated. Returns `REDISMODULE_ERR` when the\nclient doesn't exist and `REDISMODULE_OK` when the operation was successful.\n\nThe client ID is returned from the [`RedisModule_AuthenticateClientWithUser`](#RedisModule_AuthenticateClientWithUser) and\n[`RedisModule_AuthenticateClientWithACLUser`](#RedisModule_AuthenticateClientWithACLUser) APIs, but can be obtained through\nthe CLIENT api or through server events.\n\nThis function is not thread safe, and must be executed within the context\nof a command or thread safe context.\n\n<span id=\"RedisModule_RedactClientCommandArgument\"></span>"
    },
    {
      "id": "redismodule-redactclientcommandargument",
      "title": "`RedisModule_RedactClientCommandArgument`",
      "role": "content",
      "text": "int RedisModule_RedactClientCommandArgument(RedisModuleCtx *ctx, int pos);\n\n**Available since:** 7.0.0\n\nRedact the client command argument specified at the given position. Redacted arguments \nare obfuscated in user facing commands such as SLOWLOG or MONITOR, as well as\nnever being written to server logs. This command may be called multiple times on the\nsame position.\n\nNote that the command name, position 0, can not be redacted. \n\nReturns `REDISMODULE_OK` if the argument was redacted and `REDISMODULE_ERR` if there \nwas an invalid parameter passed in or the position is outside the client \nargument range.\n\n<span id=\"RedisModule_GetClientCertificate\"></span>"
    },
    {
      "id": "redismodule-getclientcertificate",
      "title": "`RedisModule_GetClientCertificate`",
      "role": "content",
      "text": "RedisModuleString *RedisModule_GetClientCertificate(RedisModuleCtx *ctx,\n                                                        uint64_t client_id);\n\n**Available since:** 6.0.9\n\nReturn the X.509 client-side certificate used by the client to authenticate\nthis connection.\n\nThe return value is an allocated `RedisModuleString` that is a X.509 certificate\nencoded in PEM (Base64) format. It should be freed (or auto-freed) by the caller.\n\nA NULL value is returned in the following conditions:\n\n- Connection ID does not exist\n- Connection is not a TLS connection\n- Connection is a TLS connection but no client certificate was used\n\n<span id=\"section-modules-dictionary-api\"></span>"
    },
    {
      "id": "modules-dictionary-api",
      "title": "Modules Dictionary API",
      "role": "content",
      "text": "Implements a sorted dictionary (actually backed by a radix tree) with\nthe usual get / set / del / num-items API, together with an iterator\ncapable of going back and forth.\n\n<span id=\"RedisModule_CreateDict\"></span>"
    },
    {
      "id": "redismodule-createdict",
      "title": "`RedisModule_CreateDict`",
      "role": "content",
      "text": "RedisModuleDict *RedisModule_CreateDict(RedisModuleCtx *ctx);\n\n**Available since:** 5.0.0\n\nCreate a new dictionary. The 'ctx' pointer can be the current module context\nor NULL, depending on what you want. Please follow the following rules:\n\n1. Use a NULL context if you plan to retain a reference to this dictionary\n   that will survive the time of the module callback where you created it.\n2. Use a NULL context if no context is available at the time you are creating\n   the dictionary (of course...).\n3. However use the current callback context as 'ctx' argument if the\n   dictionary time to live is just limited to the callback scope. In this\n   case, if enabled, you can enjoy the automatic memory management that will\n   reclaim the dictionary memory, as well as the strings returned by the\n   Next / Prev dictionary iterator calls.\n\n<span id=\"RedisModule_FreeDict\"></span>"
    },
    {
      "id": "redismodule-freedict",
      "title": "`RedisModule_FreeDict`",
      "role": "content",
      "text": "void RedisModule_FreeDict(RedisModuleCtx *ctx, RedisModuleDict *d);\n\n**Available since:** 5.0.0\n\nFree a dictionary created with [`RedisModule_CreateDict()`](#RedisModule_CreateDict). You need to pass the\ncontext pointer 'ctx' only if the dictionary was created using the\ncontext instead of passing NULL.\n\n<span id=\"RedisModule_DictSize\"></span>"
    },
    {
      "id": "redismodule-dictsize",
      "title": "`RedisModule_DictSize`",
      "role": "content",
      "text": "uint64_t RedisModule_DictSize(RedisModuleDict *d);\n\n**Available since:** 5.0.0\n\nReturn the size of the dictionary (number of keys).\n\n<span id=\"RedisModule_DictSetC\"></span>"
    },
    {
      "id": "redismodule-dictsetc",
      "title": "`RedisModule_DictSetC`",
      "role": "content",
      "text": "int RedisModule_DictSetC(RedisModuleDict *d,\n                             void *key,\n                             size_t keylen,\n                             void *ptr);\n\n**Available since:** 5.0.0\n\nStore the specified key into the dictionary, setting its value to the\npointer 'ptr'. If the key was added with success, since it did not\nalready exist, `REDISMODULE_OK` is returned. Otherwise if the key already\nexists the function returns `REDISMODULE_ERR`.\n\n<span id=\"RedisModule_DictReplaceC\"></span>"
    },
    {
      "id": "redismodule-dictreplacec",
      "title": "`RedisModule_DictReplaceC`",
      "role": "content",
      "text": "int RedisModule_DictReplaceC(RedisModuleDict *d,\n                                 void *key,\n                                 size_t keylen,\n                                 void *ptr);\n\n**Available since:** 5.0.0\n\nLike [`RedisModule_DictSetC()`](#RedisModule_DictSetC) but will replace the key with the new\nvalue if the key already exists.\n\n<span id=\"RedisModule_DictSet\"></span>"
    },
    {
      "id": "redismodule-dictset",
      "title": "`RedisModule_DictSet`",
      "role": "content",
      "text": "int RedisModule_DictSet(RedisModuleDict *d, RedisModuleString *key, void *ptr);\n\n**Available since:** 5.0.0\n\nLike [`RedisModule_DictSetC()`](#RedisModule_DictSetC) but takes the key as a `RedisModuleString`.\n\n<span id=\"RedisModule_DictReplace\"></span>"
    },
    {
      "id": "redismodule-dictreplace",
      "title": "`RedisModule_DictReplace`",
      "role": "content",
      "text": "int RedisModule_DictReplace(RedisModuleDict *d,\n                                RedisModuleString *key,\n                                void *ptr);\n\n**Available since:** 5.0.0\n\nLike [`RedisModule_DictReplaceC()`](#RedisModule_DictReplaceC) but takes the key as a `RedisModuleString`.\n\n<span id=\"RedisModule_DictGetC\"></span>"
    },
    {
      "id": "redismodule-dictgetc",
      "title": "`RedisModule_DictGetC`",
      "role": "content",
      "text": "void *RedisModule_DictGetC(RedisModuleDict *d,\n                               void *key,\n                               size_t keylen,\n                               int *nokey);\n\n**Available since:** 5.0.0\n\nReturn the value stored at the specified key. The function returns NULL\nboth in the case the key does not exist, or if you actually stored\nNULL at key. So, optionally, if the 'nokey' pointer is not NULL, it will\nbe set by reference to 1 if the key does not exist, or to 0 if the key\nexists.\n\n<span id=\"RedisModule_DictGet\"></span>"
    },
    {
      "id": "redismodule-dictget",
      "title": "`RedisModule_DictGet`",
      "role": "content",
      "text": "void *RedisModule_DictGet(RedisModuleDict *d,\n                              RedisModuleString *key,\n                              int *nokey);\n\n**Available since:** 5.0.0\n\nLike [`RedisModule_DictGetC()`](#RedisModule_DictGetC) but takes the key as a `RedisModuleString`.\n\n<span id=\"RedisModule_DictDelC\"></span>"
    },
    {
      "id": "redismodule-dictdelc",
      "title": "`RedisModule_DictDelC`",
      "role": "content",
      "text": "int RedisModule_DictDelC(RedisModuleDict *d,\n                             void *key,\n                             size_t keylen,\n                             void *oldval);\n\n**Available since:** 5.0.0\n\nRemove the specified key from the dictionary, returning `REDISMODULE_OK` if\nthe key was found and deleted, or `REDISMODULE_ERR` if instead there was\nno such key in the dictionary. When the operation is successful, if\n'oldval' is not NULL, then '*oldval' is set to the value stored at the\nkey before it was deleted. Using this feature it is possible to get\na pointer to the value (for instance in order to release it), without\nhaving to call [`RedisModule_DictGet()`](#RedisModule_DictGet) before deleting the key.\n\n<span id=\"RedisModule_DictDel\"></span>"
    },
    {
      "id": "redismodule-dictdel",
      "title": "`RedisModule_DictDel`",
      "role": "content",
      "text": "int RedisModule_DictDel(RedisModuleDict *d,\n                            RedisModuleString *key,\n                            void *oldval);\n\n**Available since:** 5.0.0\n\nLike [`RedisModule_DictDelC()`](#RedisModule_DictDelC) but gets the key as a `RedisModuleString`.\n\n<span id=\"RedisModule_DictIteratorStartC\"></span>"
    },
    {
      "id": "redismodule-dictiteratorstartc",
      "title": "`RedisModule_DictIteratorStartC`",
      "role": "content",
      "text": "RedisModuleDictIter *RedisModule_DictIteratorStartC(RedisModuleDict *d,\n                                                        const char *op,\n                                                        void *key,\n                                                        size_t keylen);\n\n**Available since:** 5.0.0\n\nReturn an iterator, setup in order to start iterating from the specified\nkey by applying the operator 'op', which is just a string specifying the\ncomparison operator to use in order to seek the first element. The\noperators available are:\n\n* `^`   – Seek the first (lexicographically smaller) key.\n* `$`   – Seek the last  (lexicographically bigger) key.\n* `>`   – Seek the first element greater than the specified key.\n* `>=`  – Seek the first element greater or equal than the specified key.\n* `<`   – Seek the first element smaller than the specified key.\n* `<=`  – Seek the first element smaller or equal than the specified key.\n* `==`  – Seek the first element matching exactly the specified key.\n\nNote that for `^` and `$` the passed key is not used, and the user may\njust pass NULL with a length of 0.\n\nIf the element to start the iteration cannot be seeked based on the\nkey and operator passed, [`RedisModule_DictNext()`](#RedisModule_DictNext) / Prev() will just return\n`REDISMODULE_ERR` at the first call, otherwise they'll produce elements.\n\n<span id=\"RedisModule_DictIteratorStart\"></span>"
    },
    {
      "id": "redismodule-dictiteratorstart",
      "title": "`RedisModule_DictIteratorStart`",
      "role": "content",
      "text": "RedisModuleDictIter *RedisModule_DictIteratorStart(RedisModuleDict *d,\n                                                       const char *op,\n                                                       RedisModuleString *key);\n\n**Available since:** 5.0.0\n\nExactly like [`RedisModule_DictIteratorStartC`](#RedisModule_DictIteratorStartC), but the key is passed as a\n`RedisModuleString`.\n\n<span id=\"RedisModule_DictIteratorStop\"></span>"
    },
    {
      "id": "redismodule-dictiteratorstop",
      "title": "`RedisModule_DictIteratorStop`",
      "role": "content",
      "text": "void RedisModule_DictIteratorStop(RedisModuleDictIter *di);\n\n**Available since:** 5.0.0\n\nRelease the iterator created with [`RedisModule_DictIteratorStart()`](#RedisModule_DictIteratorStart). This call\nis mandatory otherwise a memory leak is introduced in the module.\n\n<span id=\"RedisModule_DictIteratorReseekC\"></span>"
    },
    {
      "id": "redismodule-dictiteratorreseekc",
      "title": "`RedisModule_DictIteratorReseekC`",
      "role": "content",
      "text": "int RedisModule_DictIteratorReseekC(RedisModuleDictIter *di,\n                                        const char *op,\n                                        void *key,\n                                        size_t keylen);\n\n**Available since:** 5.0.0\n\nAfter its creation with [`RedisModule_DictIteratorStart()`](#RedisModule_DictIteratorStart), it is possible to\nchange the currently selected element of the iterator by using this\nAPI call. The result based on the operator and key is exactly like\nthe function [`RedisModule_DictIteratorStart()`](#RedisModule_DictIteratorStart), however in this case the\nreturn value is just `REDISMODULE_OK` in case the seeked element was found,\nor `REDISMODULE_ERR` in case it was not possible to seek the specified\nelement. It is possible to reseek an iterator as many times as you want.\n\n<span id=\"RedisModule_DictIteratorReseek\"></span>"
    },
    {
      "id": "redismodule-dictiteratorreseek",
      "title": "`RedisModule_DictIteratorReseek`",
      "role": "content",
      "text": "int RedisModule_DictIteratorReseek(RedisModuleDictIter *di,\n                                       const char *op,\n                                       RedisModuleString *key);\n\n**Available since:** 5.0.0\n\nLike [`RedisModule_DictIteratorReseekC()`](#RedisModule_DictIteratorReseekC) but takes the key as a\n`RedisModuleString`.\n\n<span id=\"RedisModule_DictNextC\"></span>"
    },
    {
      "id": "redismodule-dictnextc",
      "title": "`RedisModule_DictNextC`",
      "role": "content",
      "text": "void *RedisModule_DictNextC(RedisModuleDictIter *di,\n                                size_t *keylen,\n                                void **dataptr);\n\n**Available since:** 5.0.0\n\nReturn the current item of the dictionary iterator `di` and steps to the\nnext element. If the iterator already yield the last element and there\nare no other elements to return, NULL is returned, otherwise a pointer\nto a string representing the key is provided, and the `*keylen` length\nis set by reference (if keylen is not NULL). The `*dataptr`, if not NULL\nis set to the value of the pointer stored at the returned key as auxiliary\ndata (as set by the [`RedisModule_DictSet`](#RedisModule_DictSet) API).\n\nUsage example:\n\n     ... create the iterator here ...\n     char *key;\n     void *data;\n     while((key = RedisModule_DictNextC(iter,&keylen,&data)) != NULL) {\n         printf(\"%.*s %p\\n\", (int)keylen, key, data);\n     }\n\nThe returned pointer is of type void because sometimes it makes sense\nto cast it to a `char*` sometimes to an unsigned `char*` depending on the\nfact it contains or not binary data, so this API ends being more\ncomfortable to use.\n\nThe validity of the returned pointer is until the next call to the\nnext/prev iterator step. Also the pointer is no longer valid once the\niterator is released.\n\n<span id=\"RedisModule_DictPrevC\"></span>"
    },
    {
      "id": "redismodule-dictprevc",
      "title": "`RedisModule_DictPrevC`",
      "role": "content",
      "text": "void *RedisModule_DictPrevC(RedisModuleDictIter *di,\n                                size_t *keylen,\n                                void **dataptr);\n\n**Available since:** 5.0.0\n\nThis function is exactly like [`RedisModule_DictNext()`](#RedisModule_DictNext) but after returning\nthe currently selected element in the iterator, it selects the previous\nelement (lexicographically smaller) instead of the next one.\n\n<span id=\"RedisModule_DictNext\"></span>"
    },
    {
      "id": "redismodule-dictnext",
      "title": "`RedisModule_DictNext`",
      "role": "content",
      "text": "RedisModuleString *RedisModule_DictNext(RedisModuleCtx *ctx,\n                                            RedisModuleDictIter *di,\n                                            void **dataptr);\n\n**Available since:** 5.0.0\n\nLike `RedisModuleNextC()`, but instead of returning an internally allocated\nbuffer and key length, it returns directly a module string object allocated\nin the specified context 'ctx' (that may be NULL exactly like for the main\nAPI [`RedisModule_CreateString`](#RedisModule_CreateString)).\n\nThe returned string object should be deallocated after use, either manually\nor by using a context that has automatic memory management active.\n\n<span id=\"RedisModule_DictPrev\"></span>"
    },
    {
      "id": "redismodule-dictprev",
      "title": "`RedisModule_DictPrev`",
      "role": "content",
      "text": "RedisModuleString *RedisModule_DictPrev(RedisModuleCtx *ctx,\n                                            RedisModuleDictIter *di,\n                                            void **dataptr);\n\n**Available since:** 5.0.0\n\nLike [`RedisModule_DictNext()`](#RedisModule_DictNext) but after returning the currently selected\nelement in the iterator, it selects the previous element (lexicographically\nsmaller) instead of the next one.\n\n<span id=\"RedisModule_DictCompareC\"></span>"
    },
    {
      "id": "redismodule-dictcomparec",
      "title": "`RedisModule_DictCompareC`",
      "role": "content",
      "text": "int RedisModule_DictCompareC(RedisModuleDictIter *di,\n                                 const char *op,\n                                 void *key,\n                                 size_t keylen);\n\n**Available since:** 5.0.0\n\nCompare the element currently pointed by the iterator to the specified\nelement given by key/keylen, according to the operator 'op' (the set of\nvalid operators are the same valid for [`RedisModule_DictIteratorStart`](#RedisModule_DictIteratorStart)).\nIf the comparison is successful the command returns `REDISMODULE_OK`\notherwise `REDISMODULE_ERR` is returned.\n\nThis is useful when we want to just emit a lexicographical range, so\nin the loop, as we iterate elements, we can also check if we are still\non range.\n\nThe function return `REDISMODULE_ERR` if the iterator reached the\nend of elements condition as well.\n\n<span id=\"RedisModule_DictCompare\"></span>"
    },
    {
      "id": "redismodule-dictcompare",
      "title": "`RedisModule_DictCompare`",
      "role": "content",
      "text": "int RedisModule_DictCompare(RedisModuleDictIter *di,\n                                const char *op,\n                                RedisModuleString *key);\n\n**Available since:** 5.0.0\n\nLike [`RedisModule_DictCompareC`](#RedisModule_DictCompareC) but gets the key to compare with the current\niterator key as a `RedisModuleString`.\n\n<span id=\"section-modules-info-fields\"></span>"
    },
    {
      "id": "modules-info-fields",
      "title": "Modules Info fields",
      "role": "content",
      "text": "<span id=\"RedisModule_InfoAddSection\"></span>"
    },
    {
      "id": "redismodule-infoaddsection",
      "title": "`RedisModule_InfoAddSection`",
      "role": "content",
      "text": "int RedisModule_InfoAddSection(RedisModuleInfoCtx *ctx, const char *name);\n\n**Available since:** 6.0.0\n\nUsed to start a new section, before adding any fields. the section name will\nbe prefixed by `<modulename>_` and must only include A-Z,a-z,0-9.\nNULL or empty string indicates the default section (only `<modulename>`) is used.\nWhen return value is `REDISMODULE_ERR`, the section should and will be skipped.\n\n<span id=\"RedisModule_InfoBeginDictField\"></span>"
    },
    {
      "id": "redismodule-infobegindictfield",
      "title": "`RedisModule_InfoBeginDictField`",
      "role": "content",
      "text": "int RedisModule_InfoBeginDictField(RedisModuleInfoCtx *ctx, const char *name);\n\n**Available since:** 6.0.0\n\nStarts a dict field, similar to the ones in INFO KEYSPACE. Use normal\n`RedisModule_InfoAddField`* functions to add the items to this field, and\nterminate with [`RedisModule_InfoEndDictField`](#RedisModule_InfoEndDictField).\n\n<span id=\"RedisModule_InfoEndDictField\"></span>"
    },
    {
      "id": "redismodule-infoenddictfield",
      "title": "`RedisModule_InfoEndDictField`",
      "role": "content",
      "text": "int RedisModule_InfoEndDictField(RedisModuleInfoCtx *ctx);\n\n**Available since:** 6.0.0\n\nEnds a dict field, see [`RedisModule_InfoBeginDictField`](#RedisModule_InfoBeginDictField)\n\n<span id=\"RedisModule_InfoAddFieldString\"></span>"
    },
    {
      "id": "redismodule-infoaddfieldstring",
      "title": "`RedisModule_InfoAddFieldString`",
      "role": "content",
      "text": "int RedisModule_InfoAddFieldString(RedisModuleInfoCtx *ctx,\n                                       const char *field,\n                                       RedisModuleString *value);\n\n**Available since:** 6.0.0\n\nUsed by `RedisModuleInfoFunc` to add info fields.\nEach field will be automatically prefixed by `<modulename>_`.\nField names or values must not include `\\r\\n` or `:`.\n\n<span id=\"RedisModule_InfoAddFieldCString\"></span>"
    },
    {
      "id": "redismodule-infoaddfieldcstring",
      "title": "`RedisModule_InfoAddFieldCString`",
      "role": "content",
      "text": "int RedisModule_InfoAddFieldCString(RedisModuleInfoCtx *ctx,\n                                        const char *field,\n                                        const char *value);\n\n**Available since:** 6.0.0\n\nSee [`RedisModule_InfoAddFieldString()`](#RedisModule_InfoAddFieldString).\n\n<span id=\"RedisModule_InfoAddFieldDouble\"></span>"
    },
    {
      "id": "redismodule-infoaddfielddouble",
      "title": "`RedisModule_InfoAddFieldDouble`",
      "role": "content",
      "text": "int RedisModule_InfoAddFieldDouble(RedisModuleInfoCtx *ctx,\n                                       const char *field,\n                                       double value);\n\n**Available since:** 6.0.0\n\nSee [`RedisModule_InfoAddFieldString()`](#RedisModule_InfoAddFieldString).\n\n<span id=\"RedisModule_InfoAddFieldLongLong\"></span>"
    },
    {
      "id": "redismodule-infoaddfieldlonglong",
      "title": "`RedisModule_InfoAddFieldLongLong`",
      "role": "content",
      "text": "int RedisModule_InfoAddFieldLongLong(RedisModuleInfoCtx *ctx,\n                                         const char *field,\n                                         long long value);\n\n**Available since:** 6.0.0\n\nSee [`RedisModule_InfoAddFieldString()`](#RedisModule_InfoAddFieldString).\n\n<span id=\"RedisModule_InfoAddFieldULongLong\"></span>"
    },
    {
      "id": "redismodule-infoaddfieldulonglong",
      "title": "`RedisModule_InfoAddFieldULongLong`",
      "role": "content",
      "text": "int RedisModule_InfoAddFieldULongLong(RedisModuleInfoCtx *ctx,\n                                          const char *field,\n                                          unsigned long long value);\n\n**Available since:** 6.0.0\n\nSee [`RedisModule_InfoAddFieldString()`](#RedisModule_InfoAddFieldString).\n\n<span id=\"RedisModule_RegisterInfoFunc\"></span>"
    },
    {
      "id": "redismodule-registerinfofunc",
      "title": "`RedisModule_RegisterInfoFunc`",
      "role": "content",
      "text": "int RedisModule_RegisterInfoFunc(RedisModuleCtx *ctx, RedisModuleInfoFunc cb);\n\n**Available since:** 6.0.0\n\nRegisters callback for the INFO command. The callback should add INFO fields\nby calling the `RedisModule_InfoAddField*()` functions.\n\n<span id=\"RedisModule_GetServerInfo\"></span>"
    },
    {
      "id": "redismodule-getserverinfo",
      "title": "`RedisModule_GetServerInfo`",
      "role": "content",
      "text": "RedisModuleServerInfoData *RedisModule_GetServerInfo(RedisModuleCtx *ctx,\n                                                         const char *section);\n\n**Available since:** 6.0.0\n\nGet information about the server similar to the one that returns from the\nINFO command. This function takes an optional 'section' argument that may\nbe NULL. The return value holds the output and can be used with\n[`RedisModule_ServerInfoGetField`](#RedisModule_ServerInfoGetField) and alike to get the individual fields.\nWhen done, it needs to be freed with [`RedisModule_FreeServerInfo`](#RedisModule_FreeServerInfo) or with the\nautomatic memory management mechanism if enabled.\n\n<span id=\"RedisModule_FreeServerInfo\"></span>"
    },
    {
      "id": "redismodule-freeserverinfo",
      "title": "`RedisModule_FreeServerInfo`",
      "role": "content",
      "text": "void RedisModule_FreeServerInfo(RedisModuleCtx *ctx,\n                                    RedisModuleServerInfoData *data);\n\n**Available since:** 6.0.0\n\nFree data created with [`RedisModule_GetServerInfo()`](#RedisModule_GetServerInfo). You need to pass the\ncontext pointer 'ctx' only if the dictionary was created using the\ncontext instead of passing NULL.\n\n<span id=\"RedisModule_ServerInfoGetField\"></span>"
    },
    {
      "id": "redismodule-serverinfogetfield",
      "title": "`RedisModule_ServerInfoGetField`",
      "role": "content",
      "text": "RedisModuleString *RedisModule_ServerInfoGetField(RedisModuleCtx *ctx,\n                                                      RedisModuleServerInfoData *data,\n                                                      const char* field);\n\n**Available since:** 6.0.0\n\nGet the value of a field from data collected with [`RedisModule_GetServerInfo()`](#RedisModule_GetServerInfo). You\nneed to pass the context pointer 'ctx' only if you want to use auto memory\nmechanism to release the returned string. Return value will be NULL if the\nfield was not found.\n\n<span id=\"RedisModule_ServerInfoGetFieldC\"></span>"
    },
    {
      "id": "redismodule-serverinfogetfieldc",
      "title": "`RedisModule_ServerInfoGetFieldC`",
      "role": "content",
      "text": "const char *RedisModule_ServerInfoGetFieldC(RedisModuleServerInfoData *data,\n                                                const char* field);\n\n**Available since:** 6.0.0\n\nSimilar to [`RedisModule_ServerInfoGetField`](#RedisModule_ServerInfoGetField), but returns a char* which should not be freed but the caller.\n\n<span id=\"RedisModule_ServerInfoGetFieldSigned\"></span>"
    },
    {
      "id": "redismodule-serverinfogetfieldsigned",
      "title": "`RedisModule_ServerInfoGetFieldSigned`",
      "role": "content",
      "text": "long long RedisModule_ServerInfoGetFieldSigned(RedisModuleServerInfoData *data,\n                                                   const char* field,\n                                                   int *out_err);\n\n**Available since:** 6.0.0\n\nGet the value of a field from data collected with [`RedisModule_GetServerInfo()`](#RedisModule_GetServerInfo). If the\nfield is not found, or is not numerical or out of range, return value will be\n0, and the optional `out_err` argument will be set to `REDISMODULE_ERR`.\n\n<span id=\"RedisModule_ServerInfoGetFieldUnsigned\"></span>"
    },
    {
      "id": "redismodule-serverinfogetfieldunsigned",
      "title": "`RedisModule_ServerInfoGetFieldUnsigned`",
      "role": "content",
      "text": "unsigned long long RedisModule_ServerInfoGetFieldUnsigned(RedisModuleServerInfoData *data,\n                                                              const char* field,\n                                                              int *out_err);\n\n**Available since:** 6.0.0\n\nGet the value of a field from data collected with [`RedisModule_GetServerInfo()`](#RedisModule_GetServerInfo). If the\nfield is not found, or is not numerical or out of range, return value will be\n0, and the optional `out_err` argument will be set to `REDISMODULE_ERR`.\n\n<span id=\"RedisModule_ServerInfoGetFieldDouble\"></span>"
    },
    {
      "id": "redismodule-serverinfogetfielddouble",
      "title": "`RedisModule_ServerInfoGetFieldDouble`",
      "role": "content",
      "text": "double RedisModule_ServerInfoGetFieldDouble(RedisModuleServerInfoData *data,\n                                                const char* field,\n                                                int *out_err);\n\n**Available since:** 6.0.0\n\nGet the value of a field from data collected with [`RedisModule_GetServerInfo()`](#RedisModule_GetServerInfo). If the\nfield is not found, or is not a double, return value will be 0, and the\noptional `out_err` argument will be set to `REDISMODULE_ERR`.\n\n<span id=\"section-modules-utility-apis\"></span>"
    },
    {
      "id": "modules-utility-apis",
      "title": "Modules utility APIs",
      "role": "content",
      "text": "<span id=\"RedisModule_GetRandomBytes\"></span>"
    },
    {
      "id": "redismodule-getrandombytes",
      "title": "`RedisModule_GetRandomBytes`",
      "role": "content",
      "text": "void RedisModule_GetRandomBytes(unsigned char *dst, size_t len);\n\n**Available since:** 5.0.0\n\nReturn random bytes using SHA1 in counter mode with a /dev/urandom\ninitialized seed. This function is fast so can be used to generate\nmany bytes without any effect on the operating system entropy pool.\nCurrently this function is not thread safe.\n\n<span id=\"RedisModule_GetRandomHexChars\"></span>"
    },
    {
      "id": "redismodule-getrandomhexchars",
      "title": "`RedisModule_GetRandomHexChars`",
      "role": "content",
      "text": "void RedisModule_GetRandomHexChars(char *dst, size_t len);\n\n**Available since:** 5.0.0\n\nLike [`RedisModule_GetRandomBytes()`](#RedisModule_GetRandomBytes) but instead of setting the string to\nrandom bytes the string is set to random characters in the in the\nhex charset [0-9a-f].\n\n<span id=\"section-modules-api-exporting-importing\"></span>"
    },
    {
      "id": "modules-api-exporting-importing",
      "title": "Modules API exporting / importing",
      "role": "content",
      "text": "<span id=\"RedisModule_ExportSharedAPI\"></span>"
    },
    {
      "id": "redismodule-exportsharedapi",
      "title": "`RedisModule_ExportSharedAPI`",
      "role": "content",
      "text": "int RedisModule_ExportSharedAPI(RedisModuleCtx *ctx,\n                                    const char *apiname,\n                                    void *func);\n\n**Available since:** 5.0.4\n\nThis function is called by a module in order to export some API with a\ngiven name. Other modules will be able to use this API by calling the\nsymmetrical function [`RedisModule_GetSharedAPI()`](#RedisModule_GetSharedAPI) and casting the return value to\nthe right function pointer.\n\nThe function will return `REDISMODULE_OK` if the name is not already taken,\notherwise `REDISMODULE_ERR` will be returned and no operation will be\nperformed.\n\nIMPORTANT: the apiname argument should be a string literal with static\nlifetime. The API relies on the fact that it will always be valid in\nthe future.\n\n<span id=\"RedisModule_GetSharedAPI\"></span>"
    },
    {
      "id": "redismodule-getsharedapi",
      "title": "`RedisModule_GetSharedAPI`",
      "role": "content",
      "text": "void *RedisModule_GetSharedAPI(RedisModuleCtx *ctx, const char *apiname);\n\n**Available since:** 5.0.4\n\nRequest an exported API pointer. The return value is just a void pointer\nthat the caller of this function will be required to cast to the right\nfunction pointer, so this is a private contract between modules.\n\nIf the requested API is not available then NULL is returned. Because\nmodules can be loaded at different times with different order, this\nfunction calls should be put inside some module generic API registering\nstep, that is called every time a module attempts to execute a\ncommand that requires external APIs: if some API cannot be resolved, the\ncommand should return an error.\n\nHere is an example:\n\n    int ... myCommandImplementation(void) {\n       if (getExternalAPIs() == 0) {\n            reply with an error here if we cannot have the APIs\n       }\n       // Use the API:\n       myFunctionPointer(foo);\n    }\n\nAnd the function registerAPI() is:\n\n    int getExternalAPIs(void) {\n        static int api_loaded = 0;\n        if (api_loaded != 0) return 1; // APIs already resolved.\n\n        myFunctionPointer = RedisModule_GetSharedAPI(\"...\");\n        if (myFunctionPointer == NULL) return 0;\n\n        return 1;\n    }\n\n<span id=\"section-module-command-filter-api\"></span>"
    },
    {
      "id": "module-command-filter-api",
      "title": "Module Command Filter API",
      "role": "content",
      "text": "<span id=\"RedisModule_RegisterCommandFilter\"></span>"
    },
    {
      "id": "redismodule-registercommandfilter",
      "title": "`RedisModule_RegisterCommandFilter`",
      "role": "content",
      "text": "RedisModuleCommandFilter *RedisModule_RegisterCommandFilter(RedisModuleCtx *ctx,\n                                                                RedisModuleCommandFilterFunc callback,\n                                                                int flags);\n\n**Available since:** 5.0.5\n\nRegister a new command filter function.\n\nCommand filtering makes it possible for modules to extend Redis by plugging\ninto the execution flow of all commands.\n\nA registered filter gets called before Redis executes *any* command.  This\nincludes both core Redis commands and commands registered by any module.  The\nfilter applies in all execution paths including:\n\n1. Invocation by a client.\n2. Invocation through [`RedisModule_Call()`](#RedisModule_Call) by any module.\n3. Invocation through Lua `redis.call()`.\n4. Replication of a command from a master.\n\nThe filter executes in a special filter context, which is different and more\nlimited than a `RedisModuleCtx`.  Because the filter affects any command, it\nmust be implemented in a very efficient way to reduce the performance impact\non Redis.  All Redis Module API calls that require a valid context (such as\n[`RedisModule_Call()`](#RedisModule_Call), [`RedisModule_OpenKey()`](#RedisModule_OpenKey), etc.) are not supported in a\nfilter context.\n\nThe `RedisModuleCommandFilterCtx` can be used to inspect or modify the\nexecuted command and its arguments.  As the filter executes before Redis\nbegins processing the command, any change will affect the way the command is\nprocessed.  For example, a module can override Redis commands this way:\n\n1. Register a `MODULE.SET` command which implements an extended version of\n   the Redis `SET` command.\n2. Register a command filter which detects invocation of `SET` on a specific\n   pattern of keys.  Once detected, the filter will replace the first\n   argument from `SET` to `MODULE.SET`.\n3. When filter execution is complete, Redis considers the new command name\n   and therefore executes the module's own command.\n\nNote that in the above use case, if `MODULE.SET` itself uses\n[`RedisModule_Call()`](#RedisModule_Call) the filter will be applied on that call as well.  If\nthat is not desired, the `REDISMODULE_CMDFILTER_NOSELF` flag can be set when\nregistering the filter.\n\nThe `REDISMODULE_CMDFILTER_NOSELF` flag prevents execution flows that\noriginate from the module's own [`RedisModule_Call()`](#RedisModule_Call) from reaching the filter.  This\nflag is effective for all execution flows, including nested ones, as long as\nthe execution begins from the module's command context or a thread-safe\ncontext that is associated with a blocking command.\n\nDetached thread-safe contexts are *not* associated with the module and cannot\nbe protected by this flag.\n\nIf multiple filters are registered (by the same or different modules), they\nare executed in the order of registration.\n\n<span id=\"RedisModule_UnregisterCommandFilter\"></span>"
    },
    {
      "id": "redismodule-unregistercommandfilter",
      "title": "`RedisModule_UnregisterCommandFilter`",
      "role": "content",
      "text": "int RedisModule_UnregisterCommandFilter(RedisModuleCtx *ctx,\n                                            RedisModuleCommandFilter *filter);\n\n**Available since:** 5.0.5\n\nUnregister a command filter.\n\n<span id=\"RedisModule_CommandFilterArgsCount\"></span>"
    },
    {
      "id": "redismodule-commandfilterargscount",
      "title": "`RedisModule_CommandFilterArgsCount`",
      "role": "content",
      "text": "int RedisModule_CommandFilterArgsCount(RedisModuleCommandFilterCtx *fctx);\n\n**Available since:** 5.0.5\n\nReturn the number of arguments a filtered command has.  The number of\narguments include the command itself.\n\n<span id=\"RedisModule_CommandFilterArgGet\"></span>"
    },
    {
      "id": "redismodule-commandfilterargget",
      "title": "`RedisModule_CommandFilterArgGet`",
      "role": "content",
      "text": "RedisModuleString *RedisModule_CommandFilterArgGet(RedisModuleCommandFilterCtx *fctx,\n                                                       int pos);\n\n**Available since:** 5.0.5\n\nReturn the specified command argument.  The first argument (position 0) is\nthe command itself, and the rest are user-provided args.\n\n<span id=\"RedisModule_CommandFilterArgInsert\"></span>"
    },
    {
      "id": "redismodule-commandfilterarginsert",
      "title": "`RedisModule_CommandFilterArgInsert`",
      "role": "content",
      "text": "int RedisModule_CommandFilterArgInsert(RedisModuleCommandFilterCtx *fctx,\n                                           int pos,\n                                           RedisModuleString *arg);\n\n**Available since:** 5.0.5\n\nModify the filtered command by inserting a new argument at the specified\nposition.  The specified `RedisModuleString` argument may be used by Redis\nafter the filter context is destroyed, so it must not be auto-memory\nallocated, freed or used elsewhere.\n\n<span id=\"RedisModule_CommandFilterArgReplace\"></span>"
    },
    {
      "id": "redismodule-commandfilterargreplace",
      "title": "`RedisModule_CommandFilterArgReplace`",
      "role": "content",
      "text": "int RedisModule_CommandFilterArgReplace(RedisModuleCommandFilterCtx *fctx,\n                                            int pos,\n                                            RedisModuleString *arg);\n\n**Available since:** 5.0.5\n\nModify the filtered command by replacing an existing argument with a new one.\nThe specified `RedisModuleString` argument may be used by Redis after the\nfilter context is destroyed, so it must not be auto-memory allocated, freed\nor used elsewhere.\n\n<span id=\"RedisModule_CommandFilterArgDelete\"></span>"
    },
    {
      "id": "redismodule-commandfilterargdelete",
      "title": "`RedisModule_CommandFilterArgDelete`",
      "role": "content",
      "text": "int RedisModule_CommandFilterArgDelete(RedisModuleCommandFilterCtx *fctx,\n                                           int pos);\n\n**Available since:** 5.0.5\n\nModify the filtered command by deleting an argument at the specified\nposition.\n\n<span id=\"RedisModule_CommandFilterGetClientId\"></span>"
    },
    {
      "id": "redismodule-commandfiltergetclientid",
      "title": "`RedisModule_CommandFilterGetClientId`",
      "role": "content",
      "text": "unsigned long long RedisModule_CommandFilterGetClientId(RedisModuleCommandFilterCtx *fctx);\n\n**Available since:** 7.2.0\n\nGet Client ID for client that issued the command we are filtering\n\n<span id=\"RedisModule_MallocSize\"></span>"
    },
    {
      "id": "redismodule-mallocsize",
      "title": "`RedisModule_MallocSize`",
      "role": "content",
      "text": "size_t RedisModule_MallocSize(void* ptr);\n\n**Available since:** 6.0.0\n\nFor a given pointer allocated via [`RedisModule_Alloc()`](#RedisModule_Alloc) or\n[`RedisModule_Realloc()`](#RedisModule_Realloc), return the amount of memory allocated for it.\nNote that this may be different (larger) than the memory we allocated\nwith the allocation calls, since sometimes the underlying allocator\nwill allocate more memory.\n\n<span id=\"RedisModule_MallocUsableSize\"></span>"
    },
    {
      "id": "redismodule-mallocusablesize",
      "title": "`RedisModule_MallocUsableSize`",
      "role": "content",
      "text": "size_t RedisModule_MallocUsableSize(void *ptr);\n\n**Available since:** 7.0.1\n\nSimilar to [`RedisModule_MallocSize`](#RedisModule_MallocSize), the difference is that [`RedisModule_MallocUsableSize`](#RedisModule_MallocUsableSize)\nreturns the usable size of memory by the module.\n\n<span id=\"RedisModule_MallocSizeString\"></span>"
    },
    {
      "id": "redismodule-mallocsizestring",
      "title": "`RedisModule_MallocSizeString`",
      "role": "content",
      "text": "size_t RedisModule_MallocSizeString(RedisModuleString* str);\n\n**Available since:** 7.0.0\n\nSame as [`RedisModule_MallocSize`](#RedisModule_MallocSize), except it works on `RedisModuleString` pointers.\n\n<span id=\"RedisModule_MallocSizeDict\"></span>"
    },
    {
      "id": "redismodule-mallocsizedict",
      "title": "`RedisModule_MallocSizeDict`",
      "role": "content",
      "text": "size_t RedisModule_MallocSizeDict(RedisModuleDict* dict);\n\n**Available since:** 7.0.0\n\nSame as [`RedisModule_MallocSize`](#RedisModule_MallocSize), except it works on `RedisModuleDict` pointers.\nNote that the returned value is only the overhead of the underlying structures,\nit does not include the allocation size of the keys and values.\n\n<span id=\"RedisModule_GetUsedMemoryRatio\"></span>"
    },
    {
      "id": "redismodule-getusedmemoryratio",
      "title": "`RedisModule_GetUsedMemoryRatio`",
      "role": "content",
      "text": "float RedisModule_GetUsedMemoryRatio(void);\n\n**Available since:** 6.0.0\n\nReturn the a number between 0 to 1 indicating the amount of memory\ncurrently used, relative to the Redis \"maxmemory\" configuration.\n\n* 0 - No memory limit configured.\n* Between 0 and 1 - The percentage of the memory used normalized in 0-1 range.\n* Exactly 1 - Memory limit reached.\n* Greater 1 - More memory used than the configured limit.\n\n<span id=\"section-scanning-keyspace-and-hashes\"></span>"
    },
    {
      "id": "scanning-keyspace-and-hashes",
      "title": "Scanning keyspace and hashes",
      "role": "content",
      "text": "<span id=\"RedisModule_ScanCursorCreate\"></span>"
    },
    {
      "id": "redismodule-scancursorcreate",
      "title": "`RedisModule_ScanCursorCreate`",
      "role": "content",
      "text": "RedisModuleScanCursor *RedisModule_ScanCursorCreate(void);\n\n**Available since:** 6.0.0\n\nCreate a new cursor to be used with [`RedisModule_Scan`](#RedisModule_Scan)\n\n<span id=\"RedisModule_ScanCursorRestart\"></span>"
    },
    {
      "id": "redismodule-scancursorrestart",
      "title": "`RedisModule_ScanCursorRestart`",
      "role": "content",
      "text": "void RedisModule_ScanCursorRestart(RedisModuleScanCursor *cursor);\n\n**Available since:** 6.0.0\n\nRestart an existing cursor. The keys will be rescanned.\n\n<span id=\"RedisModule_ScanCursorDestroy\"></span>"
    },
    {
      "id": "redismodule-scancursordestroy",
      "title": "`RedisModule_ScanCursorDestroy`",
      "role": "content",
      "text": "void RedisModule_ScanCursorDestroy(RedisModuleScanCursor *cursor);\n\n**Available since:** 6.0.0\n\nDestroy the cursor struct.\n\n<span id=\"RedisModule_Scan\"></span>"
    },
    {
      "id": "redismodule-scan",
      "title": "`RedisModule_Scan`",
      "role": "content",
      "text": "int RedisModule_Scan(RedisModuleCtx *ctx,\n                         RedisModuleScanCursor *cursor,\n                         RedisModuleScanCB fn,\n                         void *privdata);\n\n**Available since:** 6.0.0\n\nScan API that allows a module to scan all the keys and value in\nthe selected db.\n\nCallback for scan implementation.\n\n    void scan_callback(RedisModuleCtx *ctx, RedisModuleString *keyname,\n                       RedisModuleKey *key, void *privdata);\n\n- `ctx`: the redis module context provided to for the scan.\n- `keyname`: owned by the caller and need to be retained if used after this\n  function.\n- `key`: holds info on the key and value, it is provided as best effort, in\n  some cases it might be NULL, in which case the user should (can) use\n  [`RedisModule_OpenKey()`](#RedisModule_OpenKey) (and CloseKey too).\n  when it is provided, it is owned by the caller and will be free when the\n  callback returns.\n- `privdata`: the user data provided to [`RedisModule_Scan()`](#RedisModule_Scan).\n\nThe way it should be used:\n\n     RedisModuleScanCursor *c = RedisModule_ScanCursorCreate();\n     while(RedisModule_Scan(ctx, c, callback, privateData));\n     RedisModule_ScanCursorDestroy(c);\n\nIt is also possible to use this API from another thread while the lock\nis acquired during the actual call to [`RedisModule_Scan`](#RedisModule_Scan):\n\n     RedisModuleScanCursor *c = RedisModule_ScanCursorCreate();\n     RedisModule_ThreadSafeContextLock(ctx);\n     while(RedisModule_Scan(ctx, c, callback, privateData)){\n         RedisModule_ThreadSafeContextUnlock(ctx);\n         // do some background job\n         RedisModule_ThreadSafeContextLock(ctx);\n     }\n     RedisModule_ScanCursorDestroy(c);\n\nThe function will return 1 if there are more elements to scan and\n0 otherwise, possibly setting errno if the call failed.\n\nIt is also possible to restart an existing cursor using [`RedisModule_ScanCursorRestart`](#RedisModule_ScanCursorRestart).\n\nIMPORTANT: This API is very similar to the Redis SCAN command from the\npoint of view of the guarantees it provides. This means that the API\nmay report duplicated keys, but guarantees to report at least one time\nevery key that was there from the start to the end of the scanning process.\n\nNOTE: If you do database changes within the callback, you should be aware\nthat the internal state of the database may change. For instance it is safe\nto delete or modify the current key, but may not be safe to delete any\nother key.\nMoreover playing with the Redis keyspace while iterating may have the\neffect of returning more duplicates. A safe pattern is to store the keys\nnames you want to modify elsewhere, and perform the actions on the keys\nlater when the iteration is complete. However this can cost a lot of\nmemory, so it may make sense to just operate on the current key when\npossible during the iteration, given that this is safe.\n\n<span id=\"RedisModule_ScanKey\"></span>"
    },
    {
      "id": "redismodule-scankey",
      "title": "`RedisModule_ScanKey`",
      "role": "content",
      "text": "int RedisModule_ScanKey(RedisModuleKey *key,\n                            RedisModuleScanCursor *cursor,\n                            RedisModuleScanKeyCB fn,\n                            void *privdata);\n\n**Available since:** 6.0.0\n\nScan api that allows a module to scan the elements in a hash, set or sorted set key\n\nCallback for scan implementation.\n\n    void scan_callback(RedisModuleKey *key, RedisModuleString* field, RedisModuleString* value, void *privdata);\n\n- key - the redis key context provided to for the scan.\n- field - field name, owned by the caller and need to be retained if used\n  after this function.\n- value - value string or NULL for set type, owned by the caller and need to\n  be retained if used after this function.\n- privdata - the user data provided to [`RedisModule_ScanKey`](#RedisModule_ScanKey).\n\nThe way it should be used:\n\n     RedisModuleScanCursor *c = RedisModule_ScanCursorCreate();\n     RedisModuleKey *key = RedisModule_OpenKey(...);\n     while(RedisModule_ScanKey(key, c, callback, privateData));\n     RedisModule_CloseKey(key);\n     RedisModule_ScanCursorDestroy(c);\n\nIt is also possible to use this API from another thread while the lock is acquired during\nthe actual call to [`RedisModule_ScanKey`](#RedisModule_ScanKey), and re-opening the key each time:\n\n     RedisModuleScanCursor *c = RedisModule_ScanCursorCreate();\n     RedisModule_ThreadSafeContextLock(ctx);\n     RedisModuleKey *key = RedisModule_OpenKey(...);\n     while(RedisModule_ScanKey(ctx, c, callback, privateData)){\n         RedisModule_CloseKey(key);\n         RedisModule_ThreadSafeContextUnlock(ctx);\n         // do some background job\n         RedisModule_ThreadSafeContextLock(ctx);\n         key = RedisModule_OpenKey(...);\n     }\n     RedisModule_CloseKey(key);\n     RedisModule_ScanCursorDestroy(c);\n\nThe function will return 1 if there are more elements to scan and 0 otherwise,\npossibly setting errno if the call failed.\nIt is also possible to restart an existing cursor using [`RedisModule_ScanCursorRestart`](#RedisModule_ScanCursorRestart).\n\nNOTE: Certain operations are unsafe while iterating the object. For instance\nwhile the API guarantees to return at least one time all the elements that\nare present in the data structure consistently from the start to the end\nof the iteration (see HSCAN and similar commands documentation), the more\nyou play with the elements, the more duplicates you may get. In general\ndeleting the current element of the data structure is safe, while removing\nthe key you are iterating is not safe.\n\n<span id=\"section-module-fork-api\"></span>"
    },
    {
      "id": "module-fork-api",
      "title": "Module fork API",
      "role": "content",
      "text": "<span id=\"RedisModule_Fork\"></span>"
    },
    {
      "id": "redismodule-fork",
      "title": "`RedisModule_Fork`",
      "role": "content",
      "text": "int RedisModule_Fork(RedisModuleForkDoneHandler cb, void *user_data);\n\n**Available since:** 6.0.0\n\nCreate a background child process with the current frozen snapshot of the\nmain process where you can do some processing in the background without\naffecting / freezing the traffic and no need for threads and GIL locking.\nNote that Redis allows for only one concurrent fork.\nWhen the child wants to exit, it should call [`RedisModule_ExitFromChild`](#RedisModule_ExitFromChild).\nIf the parent wants to kill the child it should call [`RedisModule_KillForkChild`](#RedisModule_KillForkChild)\nThe done handler callback will be executed on the parent process when the\nchild existed (but not when killed)\nReturn: -1 on failure, on success the parent process will get a positive PID\nof the child, and the child process will get 0.\n\n<span id=\"RedisModule_SendChildHeartbeat\"></span>"
    },
    {
      "id": "redismodule-sendchildheartbeat",
      "title": "`RedisModule_SendChildHeartbeat`",
      "role": "content",
      "text": "void RedisModule_SendChildHeartbeat(double progress);\n\n**Available since:** 6.2.0\n\nThe module is advised to call this function from the fork child once in a while,\nso that it can report progress and COW memory to the parent which will be\nreported in INFO.\nThe `progress` argument should between 0 and 1, or -1 when not available.\n\n<span id=\"RedisModule_ExitFromChild\"></span>"
    },
    {
      "id": "redismodule-exitfromchild",
      "title": "`RedisModule_ExitFromChild`",
      "role": "content",
      "text": "int RedisModule_ExitFromChild(int retcode);\n\n**Available since:** 6.0.0\n\nCall from the child process when you want to terminate it.\nretcode will be provided to the done handler executed on the parent process.\n\n<span id=\"RedisModule_KillForkChild\"></span>"
    },
    {
      "id": "redismodule-killforkchild",
      "title": "`RedisModule_KillForkChild`",
      "role": "content",
      "text": "int RedisModule_KillForkChild(int child_pid);\n\n**Available since:** 6.0.0\n\nCan be used to kill the forked child process from the parent process.\n`child_pid` would be the return value of [`RedisModule_Fork`](#RedisModule_Fork).\n\n<span id=\"section-server-hooks-implementation\"></span>"
    },
    {
      "id": "server-hooks-implementation",
      "title": "Server hooks implementation",
      "role": "content",
      "text": "<span id=\"RedisModule_SubscribeToServerEvent\"></span>"
    },
    {
      "id": "redismodule-subscribetoserverevent",
      "title": "`RedisModule_SubscribeToServerEvent`",
      "role": "content",
      "text": "int RedisModule_SubscribeToServerEvent(RedisModuleCtx *ctx,\n                                           RedisModuleEvent event,\n                                           RedisModuleEventCallback callback);\n\n**Available since:** 6.0.0\n\nRegister to be notified, via a callback, when the specified server event\nhappens. The callback is called with the event as argument, and an additional\nargument which is a void pointer and should be cased to a specific type\nthat is event-specific (but many events will just use NULL since they do not\nhave additional information to pass to the callback).\n\nIf the callback is NULL and there was a previous subscription, the module\nwill be unsubscribed. If there was a previous subscription and the callback\nis not null, the old callback will be replaced with the new one.\n\nThe callback must be of this type:\n\n    int (*RedisModuleEventCallback)(RedisModuleCtx *ctx,\n                                    RedisModuleEvent eid,\n                                    uint64_t subevent,\n                                    void *data);\n\nThe 'ctx' is a normal Redis module context that the callback can use in\norder to call other modules APIs. The 'eid' is the event itself, this\nis only useful in the case the module subscribed to multiple events: using\nthe 'id' field of this structure it is possible to check if the event\nis one of the events we registered with this callback. The 'subevent' field\ndepends on the event that fired.\n\nFinally the 'data' pointer may be populated, only for certain events, with\nmore relevant data.\n\nHere is a list of events you can use as 'eid' and related sub events:\n\n* `RedisModuleEvent_ReplicationRoleChanged`:\n\n    This event is called when the instance switches from master\n    to replica or the other way around, however the event is\n    also called when the replica remains a replica but starts to\n    replicate with a different master.\n\n    The following sub events are available:\n\n    * `REDISMODULE_SUBEVENT_REPLROLECHANGED_NOW_MASTER`\n    * `REDISMODULE_SUBEVENT_REPLROLECHANGED_NOW_REPLICA`\n\n    The 'data' field can be casted by the callback to a\n    `RedisModuleReplicationInfo` structure with the following fields:\n\n        int master; // true if master, false if replica\n        char *masterhost; // master instance hostname for NOW_REPLICA\n        int masterport; // master instance port for NOW_REPLICA\n        char *replid1; // Main replication ID\n        char *replid2; // Secondary replication ID\n        uint64_t repl1_offset; // Main replication offset\n        uint64_t repl2_offset; // Offset of replid2 validity\n\n* `RedisModuleEvent_Persistence`\n\n    This event is called when RDB saving or AOF rewriting starts\n    and ends. The following sub events are available:\n\n    * `REDISMODULE_SUBEVENT_PERSISTENCE_RDB_START`\n    * `REDISMODULE_SUBEVENT_PERSISTENCE_AOF_START`\n    * `REDISMODULE_SUBEVENT_PERSISTENCE_SYNC_RDB_START`\n    * `REDISMODULE_SUBEVENT_PERSISTENCE_SYNC_AOF_START`\n    * `REDISMODULE_SUBEVENT_PERSISTENCE_ENDED`\n    * `REDISMODULE_SUBEVENT_PERSISTENCE_FAILED`\n\n    The above events are triggered not just when the user calls the\n    relevant commands like BGSAVE, but also when a saving operation\n    or AOF rewriting occurs because of internal server triggers.\n    The SYNC_RDB_START sub events are happening in the foreground due to\n    SAVE command, FLUSHALL, or server shutdown, and the other RDB and\n    AOF sub events are executed in a background fork child, so any\n    action the module takes can only affect the generated AOF or RDB,\n    but will not be reflected in the parent process and affect connected\n    clients and commands. Also note that the AOF_START sub event may end\n    up saving RDB content in case of an AOF with rdb-preamble.\n\n* `RedisModuleEvent_FlushDB`\n\n    The FLUSHALL, FLUSHDB or an internal flush (for instance\n    because of replication, after the replica synchronization)\n    happened. The following sub events are available:\n\n    * `REDISMODULE_SUBEVENT_FLUSHDB_START`\n    * `REDISMODULE_SUBEVENT_FLUSHDB_END`\n\n    The data pointer can be casted to a RedisModuleFlushInfo\n    structure with the following fields:\n\n        int32_t async;  // True if the flush is done in a thread.\n                        // See for instance FLUSHALL ASYNC.\n                        // In this case the END callback is invoked\n                        // immediately after the database is put\n                        // in the free list of the thread.\n        int32_t dbnum;  // Flushed database number, -1 for all the DBs\n                        // in the case of the FLUSHALL operation.\n\n    The start event is called *before* the operation is initiated, thus\n    allowing the callback to call DBSIZE or other operation on the\n    yet-to-free keyspace.\n\n* `RedisModuleEvent_Loading`\n\n    Called on loading operations: at startup when the server is\n    started, but also after a first synchronization when the\n    replica is loading the RDB file from the master.\n    The following sub events are available:\n\n    * `REDISMODULE_SUBEVENT_LOADING_RDB_START`\n    * `REDISMODULE_SUBEVENT_LOADING_AOF_START`\n    * `REDISMODULE_SUBEVENT_LOADING_REPL_START`\n    * `REDISMODULE_SUBEVENT_LOADING_ENDED`\n    * `REDISMODULE_SUBEVENT_LOADING_FAILED`\n\n    Note that AOF loading may start with an RDB data in case of\n    rdb-preamble, in which case you'll only receive an AOF_START event.\n\n* `RedisModuleEvent_ClientChange`\n\n    Called when a client connects or disconnects.\n    The data pointer can be casted to a RedisModuleClientInfo\n    structure, documented in RedisModule_GetClientInfoById().\n    The following sub events are available:\n\n    * `REDISMODULE_SUBEVENT_CLIENT_CHANGE_CONNECTED`\n    * `REDISMODULE_SUBEVENT_CLIENT_CHANGE_DISCONNECTED`\n\n* `RedisModuleEvent_Shutdown`\n\n    The server is shutting down. No subevents are available.\n\n* `RedisModuleEvent_ReplicaChange`\n\n    This event is called when the instance (that can be both a\n    master or a replica) get a new online replica, or lose a\n    replica since it gets disconnected.\n    The following sub events are available:\n\n    * `REDISMODULE_SUBEVENT_REPLICA_CHANGE_ONLINE`\n    * `REDISMODULE_SUBEVENT_REPLICA_CHANGE_OFFLINE`\n\n    No additional information is available so far: future versions\n    of Redis will have an API in order to enumerate the replicas\n    connected and their state.\n\n* `RedisModuleEvent_CronLoop`\n\n    This event is called every time Redis calls the serverCron()\n    function in order to do certain bookkeeping. Modules that are\n    required to do operations from time to time may use this callback.\n    Normally Redis calls this function 10 times per second, but\n    this changes depending on the \"hz\" configuration.\n    No sub events are available.\n\n    The data pointer can be casted to a RedisModuleCronLoop\n    structure with the following fields:\n\n        int32_t hz;  // Approximate number of events per second.\n\n* `RedisModuleEvent_MasterLinkChange`\n\n    This is called for replicas in order to notify when the\n    replication link becomes functional (up) with our master,\n    or when it goes down. Note that the link is not considered\n    up when we just connected to the master, but only if the\n    replication is happening correctly.\n    The following sub events are available:\n\n    * `REDISMODULE_SUBEVENT_MASTER_LINK_UP`\n    * `REDISMODULE_SUBEVENT_MASTER_LINK_DOWN`\n\n* `RedisModuleEvent_ModuleChange`\n\n    This event is called when a new module is loaded or one is unloaded.\n    The following sub events are available:\n\n    * `REDISMODULE_SUBEVENT_MODULE_LOADED`\n    * `REDISMODULE_SUBEVENT_MODULE_UNLOADED`\n\n    The data pointer can be casted to a RedisModuleModuleChange\n    structure with the following fields:\n\n        const char* module_name;  // Name of module loaded or unloaded.\n        int32_t module_version;  // Module version.\n\n* `RedisModuleEvent_LoadingProgress`\n\n    This event is called repeatedly called while an RDB or AOF file\n    is being loaded.\n    The following sub events are available:\n\n    * `REDISMODULE_SUBEVENT_LOADING_PROGRESS_RDB`\n    * `REDISMODULE_SUBEVENT_LOADING_PROGRESS_AOF`\n\n    The data pointer can be casted to a RedisModuleLoadingProgress\n    structure with the following fields:\n\n        int32_t hz;  // Approximate number of events per second.\n        int32_t progress;  // Approximate progress between 0 and 1024,\n                           // or -1 if unknown.\n\n* `RedisModuleEvent_SwapDB`\n\n    This event is called when a SWAPDB command has been successfully\n    Executed.\n    For this event call currently there is no subevents available.\n\n    The data pointer can be casted to a RedisModuleSwapDbInfo\n    structure with the following fields:\n\n        int32_t dbnum_first;    // Swap Db first dbnum\n        int32_t dbnum_second;   // Swap Db second dbnum\n\n* `RedisModuleEvent_ReplBackup`\n\n    WARNING: Replication Backup events are deprecated since Redis 7.0 and are never fired.\n    See RedisModuleEvent_ReplAsyncLoad for understanding how Async Replication Loading events\n    are now triggered when repl-diskless-load is set to swapdb.\n\n    Called when repl-diskless-load config is set to swapdb,\n    And redis needs to backup the current database for the\n    possibility to be restored later. A module with global data and\n    maybe with aux_load and aux_save callbacks may need to use this\n    notification to backup / restore / discard its globals.\n    The following sub events are available:\n\n    * `REDISMODULE_SUBEVENT_REPL_BACKUP_CREATE`\n    * `REDISMODULE_SUBEVENT_REPL_BACKUP_RESTORE`\n    * `REDISMODULE_SUBEVENT_REPL_BACKUP_DISCARD`\n\n* `RedisModuleEvent_ReplAsyncLoad`\n\n    Called when repl-diskless-load config is set to swapdb and a replication with a master of same\n    data set history (matching replication ID) occurs.\n    In which case redis serves current data set while loading new database in memory from socket.\n    Modules must have declared they support this mechanism in order to activate it, through\n    REDISMODULE_OPTIONS_HANDLE_REPL_ASYNC_LOAD flag.\n    The following sub events are available:\n\n    * `REDISMODULE_SUBEVENT_REPL_ASYNC_LOAD_STARTED`\n    * `REDISMODULE_SUBEVENT_REPL_ASYNC_LOAD_ABORTED`\n    * `REDISMODULE_SUBEVENT_REPL_ASYNC_LOAD_COMPLETED`\n\n* `RedisModuleEvent_ForkChild`\n\n    Called when a fork child (AOFRW, RDBSAVE, module fork...) is born/dies\n    The following sub events are available:\n\n    * `REDISMODULE_SUBEVENT_FORK_CHILD_BORN`\n    * `REDISMODULE_SUBEVENT_FORK_CHILD_DIED`\n\n* `RedisModuleEvent_EventLoop`\n\n    Called on each event loop iteration, once just before the event loop goes\n    to sleep or just after it wakes up.\n    The following sub events are available:\n\n    * `REDISMODULE_SUBEVENT_EVENTLOOP_BEFORE_SLEEP`\n    * `REDISMODULE_SUBEVENT_EVENTLOOP_AFTER_SLEEP`\n\n* `RedisModule_Event_Config`\n\n    Called when a configuration event happens\n    The following sub events are available:\n\n    * `REDISMODULE_SUBEVENT_CONFIG_CHANGE`\n\n    The data pointer can be casted to a RedisModuleConfigChange\n    structure with the following fields:\n\n        const char **config_names; // An array of C string pointers containing the\n                                   // name of each modified configuration item \n        uint32_t num_changes;      // The number of elements in the config_names array\n\n* `RedisModule_Event_Key`\n\n    Called when a key is removed from the keyspace. We can't modify any key in\n    the event.\n    The following sub events are available:\n\n    * `REDISMODULE_SUBEVENT_KEY_DELETED`\n    * `REDISMODULE_SUBEVENT_KEY_EXPIRED`\n    * `REDISMODULE_SUBEVENT_KEY_EVICTED`\n    * `REDISMODULE_SUBEVENT_KEY_OVERWRITTEN`\n\n    The data pointer can be casted to a RedisModuleKeyInfo\n    structure with the following fields:\n\n        RedisModuleKey *key;    // Key name\n\n* `RedisModuleEvent_ClusterSlotMigration`\n\n    Called when an atomic slot migration (ASM) event happens.\n    IMPORT events are triggered on the destination side of a slot migration\n    operation. These notifications let modules prepare for the upcoming\n    ownership change, observe successful completion once the cluster config\n    reflects the new owner, or detect a failure in which case slot ownership\n    remains with the source.\n\n    Similarly, MIGRATE events triggered on the source side of a slot\n    migration operation to let modules prepare for the ownership change and\n    observe the completion of the slot migration. MIGRATE_MODULE_PROPAGATE\n    event is triggered in the fork just before snapshot delivery; modules may\n    use it to enqueue commands that will be delivered first. See\n    RedisModule_ClusterPropagateForSlotMigration() for details.\n\n    * `REDISMODULE_SUBEVENT_CLUSTER_SLOT_MIGRATION_IMPORT_STARTED`\n    * `REDISMODULE_SUBEVENT_CLUSTER_SLOT_MIGRATION_IMPORT_FAILED`\n    * `REDISMODULE_SUBEVENT_CLUSTER_SLOT_MIGRATION_IMPORT_COMPLETED`\n    * `REDISMODULE_SUBEVENT_CLUSTER_SLOT_MIGRATION_MIGRATE_STARTED`\n    * `REDISMODULE_SUBEVENT_CLUSTER_SLOT_MIGRATION_MIGRATE_FAILED`\n    * `REDISMODULE_SUBEVENT_CLUSTER_SLOT_MIGRATION_MIGRATE_COMPLETED`\n    * `REDISMODULE_SUBEVENT_CLUSTER_SLOT_MIGRATION_MIGRATE_MODULE_PROPAGATE`\n\n    The data pointer can be casted to a RedisModuleClusterSlotMigrationInfo\n    structure with the following fields:\n\n        char source_node_id[REDISMODULE_NODE_ID_LEN + 1];\n        char destination_node_id[REDISMODULE_NODE_ID_LEN + 1];\n        const char *task_id;               // Task ID\n        RedisModuleSlotRangeArray *slots;  // Slot ranges\n\n* `RedisModuleEvent_ClusterSlotMigrationTrim`\n\n    Called when trimming keys after a slot migration. Fires on the source\n    after a successful migration to clean up migrated keys, or on the\n    destination after a failed import to discard partial imports. Two methods\n    are supported. In the first method, keys are deleted in a background\n    thread; this is reported via the TRIM_BACKGROUND event. In the second\n    method, Redis performs incremental deletions on the main thread via the\n    cron loop to avoid stalls; this is reported via the TRIM_STARTED and\n    TRIM_COMPLETED events. Each deletion emits REDISMODULE_NOTIFY_KEY_TRIMMED\n    so modules can react to individual key deletions. Redis selects the\n    method automatically: background by default; switches to main thread\n    trimming when a module subscribes to REDISMODULE_NOTIFY_KEY_TRIMMED.\n\n    The following sub events are available:\n\n    * `REDISMODULE_SUBEVENT_CLUSTER_SLOT_MIGRATION_TRIM_STARTED`\n    * `REDISMODULE_SUBEVENT_CLUSTER_SLOT_MIGRATION_TRIM_COMPLETED`\n    * `REDISMODULE_SUBEVENT_CLUSTER_SLOT_MIGRATION_TRIM_BACKGROUND`\n\n    The data pointer can be casted to a RedisModuleClusterSlotMigrationTrimInfo\n    structure with the following fields:\n\n        RedisModuleSlotRangeArray *slots;  // Slot ranges\n\nThe function returns `REDISMODULE_OK` if the module was successfully subscribed\nfor the specified event. If the API is called from a wrong context or unsupported event\nis given then `REDISMODULE_ERR` is returned.\n\n<span id=\"RedisModule_IsSubEventSupported\"></span>"
    },
    {
      "id": "redismodule-issubeventsupported",
      "title": "`RedisModule_IsSubEventSupported`",
      "role": "content",
      "text": "int RedisModule_IsSubEventSupported(RedisModuleEvent event, int64_t subevent);\n\n**Available since:** 6.0.9\n\n\nFor a given server event and subevent, return zero if the\nsubevent is not supported and non-zero otherwise.\n\n<span id=\"section-module-configurations-api\"></span>"
    },
    {
      "id": "module-configurations-api",
      "title": "Module Configurations API",
      "role": "content",
      "text": "<span id=\"RedisModule_RegisterStringConfig\"></span>"
    },
    {
      "id": "redismodule-registerstringconfig",
      "title": "`RedisModule_RegisterStringConfig`",
      "role": "content",
      "text": "int RedisModule_RegisterStringConfig(RedisModuleCtx *ctx,\n                                         const char *name,\n                                         const char *default_val,\n                                         unsigned int flags,\n                                         RedisModuleConfigGetStringFunc getfn,\n                                         RedisModuleConfigSetStringFunc setfn,\n                                         RedisModuleConfigApplyFunc applyfn,\n                                         void *privdata);\n\n**Available since:** 7.0.0\n\nCreate a string config that Redis users can interact with via the Redis config file,\n`CONFIG SET`, `CONFIG GET`, and `CONFIG REWRITE` commands.\n\nThe actual config value is owned by the module, and the `getfn`, `setfn` and optional\n`applyfn` callbacks that are provided to Redis in order to access or manipulate the\nvalue. The `getfn` callback retrieves the value from the module, while the `setfn`\ncallback provides a value to be stored into the module config.\nThe optional `applyfn` callback is called after a `CONFIG SET` command modified one or\nmore configs using the `setfn` callback and can be used to atomically apply a config\nafter several configs were changed together.\nIf there are multiple configs with `applyfn` callbacks set by a single `CONFIG SET`\ncommand, they will be deduplicated if their `applyfn` function and `privdata` pointers\nare identical, and the callback will only be run once.\nBoth the `setfn` and `applyfn` can return an error if the provided value is invalid or\ncannot be used.\nThe config also declares a type for the value that is validated by Redis and\nprovided to the module. The config system provides the following types:\n\n* Redis String: Binary safe string data.\n* Enum: One of a finite number of string tokens, provided during registration.\n* Numeric: 64 bit signed integer, which also supports min and max values.\n* Bool: Yes or no value.\n\nThe `setfn` callback is expected to return `REDISMODULE_OK` when the value is successfully\napplied. It can also return `REDISMODULE_ERR` if the value can't be applied, and the\n*err pointer can be set with a `RedisModuleString` error message to provide to the client.\nThis `RedisModuleString` will be freed by redis after returning from the set callback.\n\nAll configs are registered with a name, a type, a default value, private data that is made\navailable in the callbacks, as well as several flags that modify the behavior of the config.\nThe name must only contain alphanumeric characters or dashes. The supported flags are:\n\n* `REDISMODULE_CONFIG_DEFAULT`: The default flags for a config. This creates a config that can be modified after startup.\n* `REDISMODULE_CONFIG_IMMUTABLE`: This config can only be provided loading time.\n* `REDISMODULE_CONFIG_SENSITIVE`: The value stored in this config is redacted from all logging.\n* `REDISMODULE_CONFIG_HIDDEN`: The name is hidden from `CONFIG GET` with pattern matching.\n* `REDISMODULE_CONFIG_PROTECTED`: This config will be only be modifiable based off the value of enable-protected-configs.\n* `REDISMODULE_CONFIG_DENY_LOADING`: This config is not modifiable while the server is loading data.\n* `REDISMODULE_CONFIG_MEMORY`: For numeric configs, this config will convert data unit notations into their byte equivalent.\n* `REDISMODULE_CONFIG_BITFLAGS`: For enum configs, this config will allow multiple entries to be combined as bit flags.\n\nDefault values are used on startup to set the value if it is not provided via the config file\nor command line. Default values are also used to compare to on a config rewrite.\n\nNotes:\n\n 1. On string config sets that the string passed to the set callback will be freed after execution and the module must retain it.\n 2. On string config gets the string will not be consumed and will be valid after execution.\n\nExample implementation:\n\n    RedisModuleString *strval;\n    int adjustable = 1;\n    RedisModuleString *getStringConfigCommand(const char *name, void *privdata) {\n        return strval;\n    }\n\n    int setStringConfigCommand(const char *name, RedisModuleString *new, void *privdata, RedisModuleString **err) {\n       if (adjustable) {\n           RedisModule_Free(strval);\n           RedisModule_RetainString(NULL, new);\n           strval = new;\n           return REDISMODULE_OK;\n       }\n       *err = RedisModule_CreateString(NULL, \"Not adjustable.\", 15);\n       return REDISMODULE_ERR;\n    }\n    ...\n    RedisModule_RegisterStringConfig(ctx, \"string\", NULL, REDISMODULE_CONFIG_DEFAULT, getStringConfigCommand, setStringConfigCommand, NULL, NULL);\n\nIf the registration fails, `REDISMODULE_ERR` is returned and one of the following\nerrno is set:\n* EBUSY: Registering the Config outside of `RedisModule_OnLoad`.\n* EINVAL: The provided flags are invalid for the registration or the name of the config contains invalid characters.\n* EALREADY: The provided configuration name is already used.\n\n<span id=\"RedisModule_RegisterBoolConfig\"></span>"
    },
    {
      "id": "redismodule-registerboolconfig",
      "title": "`RedisModule_RegisterBoolConfig`",
      "role": "content",
      "text": "int RedisModule_RegisterBoolConfig(RedisModuleCtx *ctx,\n                                       const char *name,\n                                       int default_val,\n                                       unsigned int flags,\n                                       RedisModuleConfigGetBoolFunc getfn,\n                                       RedisModuleConfigSetBoolFunc setfn,\n                                       RedisModuleConfigApplyFunc applyfn,\n                                       void *privdata);\n\n**Available since:** 7.0.0\n\nCreate a bool config that server clients can interact with via the \n`CONFIG SET`, `CONFIG GET`, and `CONFIG REWRITE` commands. See \n[`RedisModule_RegisterStringConfig`](#RedisModule_RegisterStringConfig) for detailed information about configs.\n\n<span id=\"RedisModule_RegisterEnumConfig\"></span>"
    },
    {
      "id": "redismodule-registerenumconfig",
      "title": "`RedisModule_RegisterEnumConfig`",
      "role": "content",
      "text": "int RedisModule_RegisterEnumConfig(RedisModuleCtx *ctx,\n                                       const char *name,\n                                       int default_val,\n                                       unsigned int flags,\n                                       const char **enum_values,\n                                       const int *int_values,\n                                       int num_enum_vals,\n                                       RedisModuleConfigGetEnumFunc getfn,\n                                       RedisModuleConfigSetEnumFunc setfn,\n                                       RedisModuleConfigApplyFunc applyfn,\n                                       void *privdata);\n\n**Available since:** 7.0.0\n\n\nCreate an enum config that server clients can interact with via the \n`CONFIG SET`, `CONFIG GET`, and `CONFIG REWRITE` commands. \nEnum configs are a set of string tokens to corresponding integer values, where \nthe string value is exposed to Redis clients but the value passed Redis and the\nmodule is the integer value. These values are defined in `enum_values`, an array\nof null-terminated c strings, and `int_vals`, an array of enum values who has an\nindex partner in `enum_values`.\nExample Implementation:\n     const char *enum_vals[3] = {\"first\", \"second\", \"third\"};\n     const int int_vals[3] = {0, 2, 4};\n     int enum_val = 0;\n\n     int getEnumConfigCommand(const char *name, void *privdata) {\n         return enum_val;\n     }\n      \n     int setEnumConfigCommand(const char *name, int val, void *privdata, const char **err) {\n         enum_val = val;\n         return REDISMODULE_OK;\n     }\n     ...\n     RedisModule_RegisterEnumConfig(ctx, \"enum\", 0, REDISMODULE_CONFIG_DEFAULT, enum_vals, int_vals, 3, getEnumConfigCommand, setEnumConfigCommand, NULL, NULL);\n\nNote that you can use `REDISMODULE_CONFIG_BITFLAGS` so that multiple enum string\ncan be combined into one integer as bit flags, in which case you may want to\nsort your enums so that the preferred combinations are present first.\n\nSee [`RedisModule_RegisterStringConfig`](#RedisModule_RegisterStringConfig) for detailed general information about configs.\n\n<span id=\"RedisModule_RegisterNumericConfig\"></span>"
    },
    {
      "id": "redismodule-registernumericconfig",
      "title": "`RedisModule_RegisterNumericConfig`",
      "role": "content",
      "text": "int RedisModule_RegisterNumericConfig(RedisModuleCtx *ctx,\n                                          const char *name,\n                                          long long default_val,\n                                          unsigned int flags,\n                                          long long min,\n                                          long long max,\n                                          RedisModuleConfigGetNumericFunc getfn,\n                                          RedisModuleConfigSetNumericFunc setfn,\n                                          RedisModuleConfigApplyFunc applyfn,\n                                          void *privdata);\n\n**Available since:** 7.0.0\n\n\nCreate an integer config that server clients can interact with via the \n`CONFIG SET`, `CONFIG GET`, and `CONFIG REWRITE` commands. See \n[`RedisModule_RegisterStringConfig`](#RedisModule_RegisterStringConfig) for detailed information about configs.\n\n<span id=\"RedisModule_LoadDefaultConfigs\"></span>"
    },
    {
      "id": "redismodule-loaddefaultconfigs",
      "title": "`RedisModule_LoadDefaultConfigs`",
      "role": "content",
      "text": "int RedisModule_LoadDefaultConfigs(RedisModuleCtx *ctx);\n\n**Available since:** 8.0.0\n\nApplies all default configurations for the parameters the module registered.\nOnly call this function if the module would like to make changes to the\nconfiguration values before the actual values are applied by [`RedisModule_LoadConfigs`](#RedisModule_LoadConfigs).\nOtherwise it's sufficient to call [`RedisModule_LoadConfigs`](#RedisModule_LoadConfigs), it should already set the default values if needed.\nThis makes it possible to distinguish between default values and user provided values and apply other changes between setting the defaults and the user values.\nThis will return `REDISMODULE_ERR` if it is called:\n1. outside `RedisModule_OnLoad`\n2. more than once\n3. after the [`RedisModule_LoadConfigs`](#RedisModule_LoadConfigs) call\n\n<span id=\"RedisModule_LoadConfigs\"></span>"
    },
    {
      "id": "redismodule-loadconfigs",
      "title": "`RedisModule_LoadConfigs`",
      "role": "content",
      "text": "int RedisModule_LoadConfigs(RedisModuleCtx *ctx);\n\n**Available since:** 7.0.0\n\nApplies all pending configurations on the module load. This should be called\nafter all of the configurations have been registered for the module inside of `RedisModule_OnLoad`.\nThis will return `REDISMODULE_ERR` if it is called outside `RedisModule_OnLoad`.\nThis API needs to be called when configurations are provided in either `MODULE LOADEX`\nor provided as startup arguments.\n\n<span id=\"section-rdb-load-save-api\"></span>"
    },
    {
      "id": "rdb-load-save-api",
      "title": "RDB load/save API",
      "role": "content",
      "text": "<span id=\"RedisModule_RdbStreamCreateFromFile\"></span>"
    },
    {
      "id": "redismodule-rdbstreamcreatefromfile",
      "title": "`RedisModule_RdbStreamCreateFromFile`",
      "role": "content",
      "text": "RedisModuleRdbStream *RedisModule_RdbStreamCreateFromFile(const char *filename);\n\n**Available since:** 7.2.0\n\nCreate a stream object to save/load RDB to/from a file.\n\nThis function returns a pointer to `RedisModuleRdbStream` which is owned\nby the caller. It requires a call to [`RedisModule_RdbStreamFree()`](#RedisModule_RdbStreamFree) to free\nthe object.\n\n<span id=\"RedisModule_RdbStreamFree\"></span>"
    },
    {
      "id": "redismodule-rdbstreamfree",
      "title": "`RedisModule_RdbStreamFree`",
      "role": "content",
      "text": "void RedisModule_RdbStreamFree(RedisModuleRdbStream *stream);\n\n**Available since:** 7.2.0\n\nRelease an RDB stream object.\n\n<span id=\"RedisModule_RdbLoad\"></span>"
    },
    {
      "id": "redismodule-rdbload",
      "title": "`RedisModule_RdbLoad`",
      "role": "content",
      "text": "int RedisModule_RdbLoad(RedisModuleCtx *ctx,\n                            RedisModuleRdbStream *stream,\n                            int flags);\n\n**Available since:** 7.2.0\n\nLoad RDB file from the `stream`. Dataset will be cleared first and then RDB\nfile will be loaded.\n\n`flags` must be zero. This parameter is for future use.\n\nOn success `REDISMODULE_OK` is returned, otherwise `REDISMODULE_ERR` is returned\nand errno is set accordingly.\n\nExample:\n\n    RedisModuleRdbStream *s = RedisModule_RdbStreamCreateFromFile(\"exp.rdb\");\n    RedisModule_RdbLoad(ctx, s, 0);\n    RedisModule_RdbStreamFree(s);\n\n<span id=\"RedisModule_RdbSave\"></span>"
    },
    {
      "id": "redismodule-rdbsave",
      "title": "`RedisModule_RdbSave`",
      "role": "content",
      "text": "int RedisModule_RdbSave(RedisModuleCtx *ctx,\n                            RedisModuleRdbStream *stream,\n                            int flags);\n\n**Available since:** 7.2.0\n\nSave dataset to the RDB stream.\n\n`flags` must be zero. This parameter is for future use.\n\nOn success `REDISMODULE_OK` is returned, otherwise `REDISMODULE_ERR` is returned\nand errno is set accordingly.\n\nExample:\n\n    RedisModuleRdbStream *s = RedisModule_RdbStreamCreateFromFile(\"exp.rdb\");\n    RedisModule_RdbSave(ctx, s, 0);\n    RedisModule_RdbStreamFree(s);\n\n<span id=\"RedisModule_GetInternalSecret\"></span>"
    },
    {
      "id": "redismodule-getinternalsecret",
      "title": "`RedisModule_GetInternalSecret`",
      "role": "content",
      "text": "const char* RedisModule_GetInternalSecret(RedisModuleCtx *ctx, size_t *len);\n\n**Available since:** 8.0.0\n\nReturns the internal secret of the cluster.\nShould be used to authenticate as an internal connection to a node in the\ncluster, and by that gain the permissions to execute internal commands.\n\n<span id=\"section-config-access-api\"></span>"
    },
    {
      "id": "config-access-api",
      "title": "Config access API",
      "role": "content",
      "text": "<span id=\"RedisModule_ConfigIteratorCreate\"></span>"
    },
    {
      "id": "redismodule-configiteratorcreate",
      "title": "`RedisModule_ConfigIteratorCreate`",
      "role": "content",
      "text": "RedisModuleConfigIterator *RedisModule_ConfigIteratorCreate(RedisModuleCtx *ctx,\n                                                                const char *pattern);\n\n**Available since:** 8.2.0\n\nGet an iterator to all configs.\nOptional `ctx` can be provided if use of auto-memory is desired.\nOptional `pattern` can be provided to filter configs by name. If `pattern` is\nNULL all configs will be returned.\n\nThe returned iterator can be used to iterate over all configs using\n[`RedisModule_ConfigIteratorNext()`](#RedisModule_ConfigIteratorNext).\n\nExample usage:\n[code example]\n\nReturns a pointer to `RedisModuleConfigIterator`. Unless auto-memory is enabled\nthe caller is responsible for freeing the iterator using\n[`RedisModule_ConfigIteratorRelease()`](#RedisModule_ConfigIteratorRelease).\n\n<span id=\"RedisModule_ConfigIteratorRelease\"></span>"
    },
    {
      "id": "redismodule-configiteratorrelease",
      "title": "`RedisModule_ConfigIteratorRelease`",
      "role": "content",
      "text": "void RedisModule_ConfigIteratorRelease(RedisModuleCtx *ctx,\n                                           RedisModuleConfigIterator *iter);\n\n**Available since:** 8.2.0\n\nRelease the iterator returned by [`RedisModule_ConfigIteratorCreate()`](#RedisModule_ConfigIteratorCreate). If auto-memory\nis enabled and manual release is needed one must pass the same `RedisModuleCtx`\nthat was used to create the iterator.\n\n<span id=\"RedisModule_ConfigGetType\"></span>"
    },
    {
      "id": "redismodule-configgettype",
      "title": "`RedisModule_ConfigGetType`",
      "role": "content",
      "text": "int RedisModule_ConfigGetType(const char *name, RedisModuleConfigType *res);\n\n**Available since:** 8.2.0\n\nGet the type of a config as `RedisModuleConfigType`. One may use this  in order\nto get or set the values of the config with the appropriate function if the\ngeneric [`RedisModule_ConfigGet`](#RedisModule_ConfigGet) and [`RedisModule_ConfigSet`](#RedisModule_ConfigSet) APIs are performing\npoorly.\n\nIntended usage of this function is when iteration over the configs is\nperformed. See [`RedisModule_ConfigIteratorNext()`](#RedisModule_ConfigIteratorNext) for example usage. If setting\nor getting individual configs one can check the config type by hand in\nredis.conf (or via other sources if config is added by a module) and use the\nappropriate function without the need to call this function.\n\nExplanation of config types:\n - `REDISMODULE_CONFIG_TYPE_BOOL`: Config is a boolean. One can use `RedisModule_Config`(Get/Set)Bool\n - `REDISMODULE_CONFIG_TYPE_NUMERIC`: Config is a numeric value. One can use `RedisModule_Config`(Get/Set)Numeric\n - `REDISMODULE_CONFIG_TYPE_STRING`: Config is a string. One can use the generic `RedisModule_Config`(Get/Set)\n - `REDISMODULE_CONFIG_TYPE_ENUM`: Config is an enum. One can use `RedisModule_Config`(Get/Set)Enum\n\nIf a config with the given name exists `res` is populated with its type, else\n`REDISMODULE_ERR` is returned.\n\n<span id=\"RedisModule_ConfigIteratorNext\"></span>"
    },
    {
      "id": "redismodule-configiteratornext",
      "title": "`RedisModule_ConfigIteratorNext`",
      "role": "content",
      "text": "const char *RedisModule_ConfigIteratorNext(RedisModuleConfigIterator *iter);\n\n**Available since:** 8.2.0\n\nGo to the next element of the config iterator.\n\nReturns the name of the next config, or NULL if there are no more configs.\nReturned string is non-owning and thus should not be freed.\nIf a pattern was provided when creating the iterator, only configs matching\nthe pattern will be returned.\n\nSee [`RedisModule_ConfigIteratorCreate()`](#RedisModule_ConfigIteratorCreate) for example usage.\n\n<span id=\"RedisModule_ConfigGet\"></span>"
    },
    {
      "id": "redismodule-configget",
      "title": "`RedisModule_ConfigGet`",
      "role": "content",
      "text": "int RedisModule_ConfigGet(RedisModuleCtx *ctx,\n                              const char *name,\n                              RedisModuleString **res);\n\n**Available since:** 8.2.0\n\nGet the value of a config as a string. This function can be used to get the\nvalue of any config, regardless of its type.\n\nThe string is allocated by the module and must be freed by the caller unless\nauto memory is enabled.\n\nIf the config does not exist, `REDISMODULE_ERR` is returned, else `REDISMODULE_OK`\nis returned and `res` is populated with the value.\n\n<span id=\"RedisModule_ConfigGetBool\"></span>"
    },
    {
      "id": "redismodule-configgetbool",
      "title": "`RedisModule_ConfigGetBool`",
      "role": "content",
      "text": "int RedisModule_ConfigGetBool(RedisModuleCtx *ctx, const char *name, int *res);\n\n**Available since:** 8.2.0\n\nGet the value of a bool config.\n\nIf the config does not exist or is not a bool config, `REDISMODULE_ERR` is\nreturned, else `REDISMODULE_OK` is returned and `res` is populated with the\nvalue.\n\n<span id=\"RedisModule_ConfigGetEnum\"></span>"
    },
    {
      "id": "redismodule-configgetenum",
      "title": "`RedisModule_ConfigGetEnum`",
      "role": "content",
      "text": "int RedisModule_ConfigGetEnum(RedisModuleCtx *ctx,\n                                  const char *name,\n                                  RedisModuleString **res);\n\n**Available since:** 8.2.0\n\nGet the value of an enum config.\n\nIf the config does not exist or is not an enum config, `REDISMODULE_ERR` is\nreturned, else `REDISMODULE_OK` is returned and `res` is populated with the value.\nIf the config has multiple arguments they are returned as a space-separated\nstring.\n\n<span id=\"RedisModule_ConfigGetNumeric\"></span>"
    },
    {
      "id": "redismodule-configgetnumeric",
      "title": "`RedisModule_ConfigGetNumeric`",
      "role": "content",
      "text": "int RedisModule_ConfigGetNumeric(RedisModuleCtx *ctx,\n                                     const char *name,\n                                     long long *res);\n\n**Available since:** 8.2.0\n\nGet the value of a numeric config.\n\nIf the config does not exist or is not a numeric config, `REDISMODULE_ERR` is\nreturned, else `REDISMODULE_OK` is returned and `res` is populated with the\nvalue.\n\n<span id=\"RedisModule_ConfigSet\"></span>"
    },
    {
      "id": "redismodule-configset",
      "title": "`RedisModule_ConfigSet`",
      "role": "content",
      "text": "int RedisModule_ConfigSet(RedisModuleCtx *ctx,\n                              const char *name,\n                              RedisModuleString *value,\n                              RedisModuleString **err);\n\n**Available since:** 8.2.0\n\nSet the value of a config.\n\nThis function can be used to set the value of any config, regardless of its\ntype. If the config is multi-argument, the value must be a space-separated\nstring.\n\nIf the value failed to be set `REDISMODULE_ERR` will be returned and if `err`\nis not NULL, it will be populated with an error message.\n\n<span id=\"RedisModule_ConfigSetBool\"></span>"
    },
    {
      "id": "redismodule-configsetbool",
      "title": "`RedisModule_ConfigSetBool`",
      "role": "content",
      "text": "int RedisModule_ConfigSetBool(RedisModuleCtx *ctx,\n                                  const char *name,\n                                  int value,\n                                  RedisModuleString **err);\n\n**Available since:** 8.2.0\n\nSet the value of a bool config.\n\nSee [`RedisModule_ConfigSet`](#RedisModule_ConfigSet) for return value.\n\n<span id=\"RedisModule_ConfigSetEnum\"></span>"
    },
    {
      "id": "redismodule-configsetenum",
      "title": "`RedisModule_ConfigSetEnum`",
      "role": "content",
      "text": "int RedisModule_ConfigSetEnum(RedisModuleCtx *ctx,\n                                  const char *name,\n                                  RedisModuleString *value,\n                                  RedisModuleString **err);\n\n**Available since:** 8.2.0\n\nSet the value of an enum config.\n\nIf the config is multi-argument the value parameter must be a space-separated\nstring.\n\nSee [`RedisModule_ConfigSet`](#RedisModule_ConfigSet) for return value.\n\n<span id=\"RedisModule_ConfigSetNumeric\"></span>"
    },
    {
      "id": "redismodule-configsetnumeric",
      "title": "`RedisModule_ConfigSetNumeric`",
      "role": "content",
      "text": "int RedisModule_ConfigSetNumeric(RedisModuleCtx *ctx,\n                                     const char *name,\n                                     long long value,\n                                     RedisModuleString **err);\n\n**Available since:** 8.2.0\n\nSet the value of a numeric config.\nIf the value passed is meant to be a percentage, it should be passed as a\nnegative value.\nFor unsigned configs pass the value and cast to (long long) - internal type\nchecks will handle it.\n\nSee [`RedisModule_ConfigSet`](#RedisModule_ConfigSet) for return value.\n\n<span id=\"section-key-eviction-api\"></span>"
    },
    {
      "id": "key-eviction-api",
      "title": "Key eviction API",
      "role": "content",
      "text": "<span id=\"RedisModule_SetLRU\"></span>"
    },
    {
      "id": "redismodule-setlru",
      "title": "`RedisModule_SetLRU`",
      "role": "content",
      "text": "int RedisModule_SetLRU(RedisModuleKey *key, mstime_t lru_idle);\n\n**Available since:** 6.0.0\n\nSet the key last access time for LRU based eviction. not relevant if the\nservers's maxmemory policy is LFU based. Value is idle time in milliseconds.\nreturns `REDISMODULE_OK` if the LRU was updated, `REDISMODULE_ERR` otherwise.\n\n<span id=\"RedisModule_GetLRU\"></span>"
    },
    {
      "id": "redismodule-getlru",
      "title": "`RedisModule_GetLRU`",
      "role": "content",
      "text": "int RedisModule_GetLRU(RedisModuleKey *key, mstime_t *lru_idle);\n\n**Available since:** 6.0.0\n\nGets the key last access time.\nValue is idletime in milliseconds or -1 if the server's eviction policy is\nLFU based.\nreturns `REDISMODULE_OK` if when key is valid.\n\n<span id=\"RedisModule_SetLFU\"></span>"
    },
    {
      "id": "redismodule-setlfu",
      "title": "`RedisModule_SetLFU`",
      "role": "content",
      "text": "int RedisModule_SetLFU(RedisModuleKey *key, long long lfu_freq);\n\n**Available since:** 6.0.0\n\nSet the key access frequency. only relevant if the server's maxmemory policy\nis LFU based.\nThe frequency is a logarithmic counter that provides an indication of\nthe access frequencyonly (must be <= 255).\nreturns `REDISMODULE_OK` if the LFU was updated, `REDISMODULE_ERR` otherwise.\n\n<span id=\"RedisModule_GetLFU\"></span>"
    },
    {
      "id": "redismodule-getlfu",
      "title": "`RedisModule_GetLFU`",
      "role": "content",
      "text": "int RedisModule_GetLFU(RedisModuleKey *key, long long *lfu_freq);\n\n**Available since:** 6.0.0\n\nGets the key access frequency or -1 if the server's eviction policy is not\nLFU based.\nreturns `REDISMODULE_OK` if when key is valid.\n\n<span id=\"section-miscellaneous-apis\"></span>"
    },
    {
      "id": "miscellaneous-apis",
      "title": "Miscellaneous APIs",
      "role": "content",
      "text": "<span id=\"RedisModule_GetModuleOptionsAll\"></span>"
    },
    {
      "id": "redismodule-getmoduleoptionsall",
      "title": "`RedisModule_GetModuleOptionsAll`",
      "role": "content",
      "text": "int RedisModule_GetModuleOptionsAll(void);\n\n**Available since:** 7.2.0\n\n\nReturns the full module options flags mask, using the return value\nthe module can check if a certain set of module options are supported\nby the redis server version in use.\nExample:\n\n       int supportedFlags = RedisModule_GetModuleOptionsAll();\n       if (supportedFlags & REDISMODULE_OPTIONS_ALLOW_NESTED_KEYSPACE_NOTIFICATIONS) {\n             // REDISMODULE_OPTIONS_ALLOW_NESTED_KEYSPACE_NOTIFICATIONS is supported\n       } else{\n             // REDISMODULE_OPTIONS_ALLOW_NESTED_KEYSPACE_NOTIFICATIONS is not supported\n       }\n\n<span id=\"RedisModule_GetContextFlagsAll\"></span>"
    },
    {
      "id": "redismodule-getcontextflagsall",
      "title": "`RedisModule_GetContextFlagsAll`",
      "role": "content",
      "text": "int RedisModule_GetContextFlagsAll(void);\n\n**Available since:** 6.0.9\n\n\nReturns the full ContextFlags mask, using the return value\nthe module can check if a certain set of flags are supported\nby the redis server version in use.\nExample:\n\n       int supportedFlags = RedisModule_GetContextFlagsAll();\n       if (supportedFlags & REDISMODULE_CTX_FLAGS_MULTI) {\n             // REDISMODULE_CTX_FLAGS_MULTI is supported\n       } else{\n             // REDISMODULE_CTX_FLAGS_MULTI is not supported\n       }\n\n<span id=\"RedisModule_GetKeyspaceNotificationFlagsAll\"></span>"
    },
    {
      "id": "redismodule-getkeyspacenotificationflagsall",
      "title": "`RedisModule_GetKeyspaceNotificationFlagsAll`",
      "role": "content",
      "text": "int RedisModule_GetKeyspaceNotificationFlagsAll(void);\n\n**Available since:** 6.0.9\n\n\nReturns the full KeyspaceNotification mask, using the return value\nthe module can check if a certain set of flags are supported\nby the redis server version in use.\nExample:\n\n       int supportedFlags = RedisModule_GetKeyspaceNotificationFlagsAll();\n       if (supportedFlags & REDISMODULE_NOTIFY_LOADED) {\n             // REDISMODULE_NOTIFY_LOADED is supported\n       } else{\n             // REDISMODULE_NOTIFY_LOADED is not supported\n       }\n\n<span id=\"RedisModule_GetServerVersion\"></span>"
    },
    {
      "id": "redismodule-getserverversion",
      "title": "`RedisModule_GetServerVersion`",
      "role": "content",
      "text": "int RedisModule_GetServerVersion(void);\n\n**Available since:** 6.0.9\n\n\nReturn the redis version in format of 0x00MMmmpp.\nExample for 6.0.7 the return value will be 0x00060007.\n\n<span id=\"RedisModule_GetTypeMethodVersion\"></span>"
    },
    {
      "id": "redismodule-gettypemethodversion",
      "title": "`RedisModule_GetTypeMethodVersion`",
      "role": "content",
      "text": "int RedisModule_GetTypeMethodVersion(void);\n\n**Available since:** 6.2.0\n\n\nReturn the current redis-server runtime value of `REDISMODULE_TYPE_METHOD_VERSION`.\nYou can use that when calling [`RedisModule_CreateDataType`](#RedisModule_CreateDataType) to know which fields of\n`RedisModuleTypeMethods` are gonna be supported and which will be ignored.\n\n<span id=\"RedisModule_ModuleTypeReplaceValue\"></span>"
    },
    {
      "id": "redismodule-moduletypereplacevalue",
      "title": "`RedisModule_ModuleTypeReplaceValue`",
      "role": "content",
      "text": "int RedisModule_ModuleTypeReplaceValue(RedisModuleKey *key,\n                                           moduleType *mt,\n                                           void *new_value,\n                                           void **old_value);\n\n**Available since:** 6.0.0\n\nReplace the value assigned to a module type.\n\nThe key must be open for writing, have an existing value, and have a moduleType\nthat matches the one specified by the caller.\n\nUnlike [`RedisModule_ModuleTypeSetValue()`](#RedisModule_ModuleTypeSetValue) which will free the old value, this function\nsimply swaps the old value with the new value.\n\nThe function returns `REDISMODULE_OK` on success, `REDISMODULE_ERR` on errors\nsuch as:\n\n1. Key is not opened for writing.\n2. Key is not a module data type key.\n3. Key is a module datatype other than 'mt'.\n\nIf `old_value` is non-NULL, the old value is returned by reference.\n\n<span id=\"RedisModule_GetCommandKeysWithFlags\"></span>"
    },
    {
      "id": "redismodule-getcommandkeyswithflags",
      "title": "`RedisModule_GetCommandKeysWithFlags`",
      "role": "content",
      "text": "int *RedisModule_GetCommandKeysWithFlags(RedisModuleCtx *ctx,\n                                             RedisModuleString **argv,\n                                             int argc,\n                                             int *num_keys,\n                                             int **out_flags);\n\n**Available since:** 7.0.0\n\nFor a specified command, parse its arguments and return an array that\ncontains the indexes of all key name arguments. This function is\nessentially a more efficient way to do `COMMAND GETKEYS`.\n\nThe `out_flags` argument is optional, and can be set to NULL.\nWhen provided it is filled with `REDISMODULE_CMD_KEY_` flags in matching\nindexes with the key indexes of the returned array.\n\nA NULL return value indicates the specified command has no keys, or\nan error condition. Error conditions are indicated by setting errno\nas follows:\n\n* ENOENT: Specified command does not exist.\n* EINVAL: Invalid command arity specified.\n\nNOTE: The returned array is not a Redis Module object so it does not\nget automatically freed even when auto-memory is used. The caller\nmust explicitly call [`RedisModule_Free()`](#RedisModule_Free) to free it, same as the `out_flags` pointer if\nused.\n\n<span id=\"RedisModule_GetCommandKeys\"></span>"
    },
    {
      "id": "redismodule-getcommandkeys",
      "title": "`RedisModule_GetCommandKeys`",
      "role": "content",
      "text": "int *RedisModule_GetCommandKeys(RedisModuleCtx *ctx,\n                                    RedisModuleString **argv,\n                                    int argc,\n                                    int *num_keys);\n\n**Available since:** 6.0.9\n\nIdentical to [`RedisModule_GetCommandKeysWithFlags`](#RedisModule_GetCommandKeysWithFlags) when flags are not needed.\n\n<span id=\"RedisModule_GetCurrentCommandName\"></span>"
    },
    {
      "id": "redismodule-getcurrentcommandname",
      "title": "`RedisModule_GetCurrentCommandName`",
      "role": "content",
      "text": "const char *RedisModule_GetCurrentCommandName(RedisModuleCtx *ctx);\n\n**Available since:** 6.2.5\n\nReturn the name of the command currently running\n\n<span id=\"section-defrag-api\"></span>"
    },
    {
      "id": "defrag-api",
      "title": "Defrag API",
      "role": "content",
      "text": "<span id=\"RedisModule_RegisterDefragFunc\"></span>"
    },
    {
      "id": "redismodule-registerdefragfunc",
      "title": "`RedisModule_RegisterDefragFunc`",
      "role": "content",
      "text": "int RedisModule_RegisterDefragFunc(RedisModuleCtx *ctx,\n                                       RedisModuleDefragFunc cb);\n\n**Available since:** 6.2.0\n\nRegister a defrag callback for global data, i.e. anything that the module\nmay allocate that is not tied to a specific data type.\n\n<span id=\"RedisModule_RegisterDefragFunc2\"></span>"
    },
    {
      "id": "redismodule-registerdefragfunc2",
      "title": "`RedisModule_RegisterDefragFunc2`",
      "role": "content",
      "text": "int RedisModule_RegisterDefragFunc2(RedisModuleCtx *ctx,\n                                        RedisModuleDefragFunc2 cb);\n\n**Available since:** 8.0.0\n\nRegister a defrag callback for global data, i.e. anything that the module\nmay allocate that is not tied to a specific data type.\nThis is a more advanced version of [`RedisModule_RegisterDefragFunc`](#RedisModule_RegisterDefragFunc), in that it takes\na callbacks that has a return value, and can use [`RedisModule_DefragShouldStop`](#RedisModule_DefragShouldStop)\nin and indicate that it should be called again later, or is it done (returned 0).\n\n<span id=\"RedisModule_RegisterDefragCallbacks\"></span>"
    },
    {
      "id": "redismodule-registerdefragcallbacks",
      "title": "`RedisModule_RegisterDefragCallbacks`",
      "role": "content",
      "text": "int RedisModule_RegisterDefragCallbacks(RedisModuleCtx *ctx,\n                                            RedisModuleDefragFunc start,\n                                            RedisModuleDefragFunc end);\n\n**Available since:** 8.0.0\n\nRegister a defrag callbacks that will be called when defrag operation starts and ends.\n\nThe callbacks are the same as [`RedisModule_RegisterDefragFunc`](#RedisModule_RegisterDefragFunc) but the user\ncan also assume the callbacks are called when the defrag operation starts and ends.\n\n<span id=\"RedisModule_DefragShouldStop\"></span>"
    },
    {
      "id": "redismodule-defragshouldstop",
      "title": "`RedisModule_DefragShouldStop`",
      "role": "content",
      "text": "int RedisModule_DefragShouldStop(RedisModuleDefragCtx *ctx);\n\n**Available since:** 6.2.0\n\nWhen the data type defrag callback iterates complex structures, this\nfunction should be called periodically. A zero (false) return\nindicates the callback may continue its work. A non-zero value (true)\nindicates it should stop.\n\nWhen stopped, the callback may use [`RedisModule_DefragCursorSet()`](#RedisModule_DefragCursorSet) to store its\nposition so it can later use [`RedisModule_DefragCursorGet()`](#RedisModule_DefragCursorGet) to resume defragging.\n\nWhen stopped and more work is left to be done, the callback should\nreturn 1. Otherwise, it should return 0.\n\n<span id=\"RedisModule_DefragCursorSet\"></span>"
    },
    {
      "id": "redismodule-defragcursorset",
      "title": "`RedisModule_DefragCursorSet`",
      "role": "content",
      "text": "int RedisModule_DefragCursorSet(RedisModuleDefragCtx *ctx,\n                                    unsigned long cursor);\n\n**Available since:** 6.2.0\n\nStore an arbitrary cursor value for future re-use.\n\nThis should only be called if [`RedisModule_DefragShouldStop()`](#RedisModule_DefragShouldStop) has returned a non-zero\nvalue and the defrag callback is about to exit without fully iterating its\ndata type.\n\nThis behavior is reserved to cases where late defrag is performed. Late\ndefrag is selected for keys that implement the `free_effort` callback and\nreturn a `free_effort` value that is larger than the defrag\n'active-defrag-max-scan-fields' configuration directive.\n\nSmaller keys, keys that do not implement `free_effort` or the global\ndefrag callback are not called in late-defrag mode. In those cases, a\ncall to this function will return `REDISMODULE_ERR`.\n\nThe cursor may be used by the module to represent some progress into the\nmodule's data type. Modules may also store additional cursor-related\ninformation locally and use the cursor as a flag that indicates when\ntraversal of a new key begins. This is possible because the API makes\na guarantee that concurrent defragmentation of multiple keys will\nnot be performed.\n\n<span id=\"RedisModule_DefragCursorGet\"></span>"
    },
    {
      "id": "redismodule-defragcursorget",
      "title": "`RedisModule_DefragCursorGet`",
      "role": "content",
      "text": "int RedisModule_DefragCursorGet(RedisModuleDefragCtx *ctx,\n                                    unsigned long *cursor);\n\n**Available since:** 6.2.0\n\nFetch a cursor value that has been previously stored using [`RedisModule_DefragCursorSet()`](#RedisModule_DefragCursorSet).\n\nIf not called for a late defrag operation, `REDISMODULE_ERR` will be returned and\nthe cursor should be ignored. See [`RedisModule_DefragCursorSet()`](#RedisModule_DefragCursorSet) for more details on\ndefrag cursors.\n\n<span id=\"RedisModule_DefragAlloc\"></span>"
    },
    {
      "id": "redismodule-defragalloc",
      "title": "`RedisModule_DefragAlloc`",
      "role": "content",
      "text": "void *RedisModule_DefragAlloc(RedisModuleDefragCtx *ctx, void *ptr);\n\n**Available since:** 6.2.0\n\nDefrag a memory allocation previously allocated by [`RedisModule_Alloc`](#RedisModule_Alloc), [`RedisModule_Calloc`](#RedisModule_Calloc), etc.\nThe defragmentation process involves allocating a new memory block and copying\nthe contents to it, like `realloc()`.\n\nIf defragmentation was not necessary, NULL is returned and the operation has\nno other effect.\n\nIf a non-NULL value is returned, the caller should use the new pointer instead\nof the old one and update any reference to the old pointer, which must not\nbe used again.\n\n<span id=\"RedisModule_DefragAllocRaw\"></span>"
    },
    {
      "id": "redismodule-defragallocraw",
      "title": "`RedisModule_DefragAllocRaw`",
      "role": "content",
      "text": "void *RedisModule_DefragAllocRaw(RedisModuleDefragCtx *ctx, size_t size);\n\n**Available since:** 8.0.0\n\nAllocate memory for defrag purposes\n\nOn the common cases user simply want to reallocate a pointer with a single\nowner. For such usecase [`RedisModule_DefragAlloc`](#RedisModule_DefragAlloc) is enough. But on some usecases the user\nmight want to replace a pointer with multiple owners in different keys.\nIn such case, an in place replacement can not work because the other key still\nkeep a pointer to the old value. \n\n[`RedisModule_DefragAllocRaw`](#RedisModule_DefragAllocRaw) and [`RedisModule_DefragFreeRaw`](#RedisModule_DefragFreeRaw) allows to control when the memory\nfor defrag purposes will be allocated and when it will be freed,\nallow to support more complex defrag usecases.\n\n<span id=\"RedisModule_DefragFreeRaw\"></span>"
    },
    {
      "id": "redismodule-defragfreeraw",
      "title": "`RedisModule_DefragFreeRaw`",
      "role": "content",
      "text": "void RedisModule_DefragFreeRaw(RedisModuleDefragCtx *ctx, void *ptr);\n\n**Available since:** 8.0.0\n\nFree memory for defrag purposes\n\nSee [`RedisModule_DefragAllocRaw`](#RedisModule_DefragAllocRaw) for more information.\n\n<span id=\"RedisModule_DefragRedisModuleString\"></span>"
    },
    {
      "id": "redismodule-defragredismodulestring",
      "title": "`RedisModule_DefragRedisModuleString`",
      "role": "content",
      "text": "RedisModuleString *RedisModule_DefragRedisModuleString(RedisModuleDefragCtx *ctx,\n                                                           RedisModuleString *str);\n\n**Available since:** 6.2.0\n\nDefrag a `RedisModuleString` previously allocated by [`RedisModule_Alloc`](#RedisModule_Alloc), [`RedisModule_Calloc`](#RedisModule_Calloc), etc.\nSee [`RedisModule_DefragAlloc()`](#RedisModule_DefragAlloc) for more information on how the defragmentation process\nworks.\n\nNOTE: It is only possible to defrag strings that have a single reference.\nTypically this means strings retained with [`RedisModule_RetainString`](#RedisModule_RetainString) or [`RedisModule_HoldString`](#RedisModule_HoldString)\nmay not be defragmentable. One exception is command argvs which, if retained\nby the module, will end up with a single reference (because the reference\non the Redis side is dropped as soon as the command callback returns).\n\n<span id=\"RedisModule_DefragRedisModuleDict\"></span>"
    },
    {
      "id": "redismodule-defragredismoduledict",
      "title": "`RedisModule_DefragRedisModuleDict`",
      "role": "content",
      "text": "RedisModuleDict *RedisModule_DefragRedisModuleDict(RedisModuleDefragCtx *ctx,\n                                                       RedisModuleDict *dict,\n                                                       RedisModuleDefragDictValueCallback valueCB,\n                                                       RedisModuleString **seekTo);\n\n**Available since:** 8.0.0\n\nDefragment a Redis Module Dictionary by scanning its contents and calling a value\ncallback for each value.\n\nThe callback gets the current value in the dict, and should update newptr to the new pointer,\nif the value was re-allocated to a different address. The callback also gets the key name just as a reference.\nThe callback returns 0 when defrag is complete for this node, 1 when node needs more work.\n\nThe API can work incrementally by accepting a seek position to continue from, and\nreturning the next position to seek to on the next call (or return NULL when the iteration is completed).\n\nThis API returns a new dict if it was re-allocated to a new address (will only\nbe attempted when *seekTo is NULL on entry).\n\n<span id=\"RedisModule_GetKeyNameFromDefragCtx\"></span>"
    },
    {
      "id": "redismodule-getkeynamefromdefragctx",
      "title": "`RedisModule_GetKeyNameFromDefragCtx`",
      "role": "content",
      "text": "const RedisModuleString *RedisModule_GetKeyNameFromDefragCtx(RedisModuleDefragCtx *ctx);\n\n**Available since:** 7.0.0\n\nReturns the name of the key currently being processed.\nThere is no guarantee that the key name is always available, so this may return NULL.\n\n<span id=\"RedisModule_GetDbIdFromDefragCtx\"></span>"
    },
    {
      "id": "redismodule-getdbidfromdefragctx",
      "title": "`RedisModule_GetDbIdFromDefragCtx`",
      "role": "content",
      "text": "int RedisModule_GetDbIdFromDefragCtx(RedisModuleDefragCtx *ctx);\n\n**Available since:** 7.0.0\n\nReturns the database id of the key currently being processed.\nThere is no guarantee that this info is always available, so this may return -1.\n\n<span id=\"section-function-index\"></span>"
    },
    {
      "id": "function-index",
      "title": "Function index",
      "role": "content",
      "text": "* [`RedisModule_ACLAddLogEntry`](#RedisModule_ACLAddLogEntry)\n* [`RedisModule_ACLAddLogEntryByUserName`](#RedisModule_ACLAddLogEntryByUserName)\n* [`RedisModule_ACLCheckChannelPermissions`](#RedisModule_ACLCheckChannelPermissions)\n* [`RedisModule_ACLCheckCommandPermissions`](#RedisModule_ACLCheckCommandPermissions)\n* [`RedisModule_ACLCheckKeyPermissions`](#RedisModule_ACLCheckKeyPermissions)\n* [`RedisModule_ACLCheckKeyPrefixPermissions`](#RedisModule_ACLCheckKeyPrefixPermissions)\n* [`RedisModule_AbortBlock`](#RedisModule_AbortBlock)\n* [`RedisModule_AddACLCategory`](#RedisModule_AddACLCategory)\n* [`RedisModule_AddPostNotificationJob`](#RedisModule_AddPostNotificationJob)\n* [`RedisModule_Alloc`](#RedisModule_Alloc)\n* [`RedisModule_AuthenticateClientWithACLUser`](#RedisModule_AuthenticateClientWithACLUser)\n* [`RedisModule_AuthenticateClientWithUser`](#RedisModule_AuthenticateClientWithUser)\n* [`RedisModule_AutoMemory`](#RedisModule_AutoMemory)\n* [`RedisModule_AvoidReplicaTraffic`](#RedisModule_AvoidReplicaTraffic)\n* [`RedisModule_BlockClient`](#RedisModule_BlockClient)\n* [`RedisModule_BlockClientGetPrivateData`](#RedisModule_BlockClientGetPrivateData)\n* [`RedisModule_BlockClientOnAuth`](#RedisModule_BlockClientOnAuth)\n* [`RedisModule_BlockClientOnKeys`](#RedisModule_BlockClientOnKeys)\n* [`RedisModule_BlockClientOnKeysWithFlags`](#RedisModule_BlockClientOnKeysWithFlags)\n* [`RedisModule_BlockClientSetPrivateData`](#RedisModule_BlockClientSetPrivateData)\n* [`RedisModule_BlockedClientDisconnected`](#RedisModule_BlockedClientDisconnected)\n* [`RedisModule_BlockedClientMeasureTimeEnd`](#RedisModule_BlockedClientMeasureTimeEnd)\n* [`RedisModule_BlockedClientMeasureTimeStart`](#RedisModule_BlockedClientMeasureTimeStart)\n* [`RedisModule_CachedMicroseconds`](#RedisModule_CachedMicroseconds)\n* [`RedisModule_Call`](#RedisModule_Call)\n* [`RedisModule_CallReplyArrayElement`](#RedisModule_CallReplyArrayElement)\n* [`RedisModule_CallReplyAttribute`](#RedisModule_CallReplyAttribute)\n* [`RedisModule_CallReplyAttributeElement`](#RedisModule_CallReplyAttributeElement)\n* [`RedisModule_CallReplyBigNumber`](#RedisModule_CallReplyBigNumber)\n* [`RedisModule_CallReplyBool`](#RedisModule_CallReplyBool)\n* [`RedisModule_CallReplyDouble`](#RedisModule_CallReplyDouble)\n* [`RedisModule_CallReplyInteger`](#RedisModule_CallReplyInteger)\n* [`RedisModule_CallReplyLength`](#RedisModule_CallReplyLength)\n* [`RedisModule_CallReplyMapElement`](#RedisModule_CallReplyMapElement)\n* [`RedisModule_CallReplyPromiseAbort`](#RedisModule_CallReplyPromiseAbort)\n* [`RedisModule_CallReplyPromiseSetUnblockHandler`](#RedisModule_CallReplyPromiseSetUnblockHandler)\n* [`RedisModule_CallReplyProto`](#RedisModule_CallReplyProto)\n* [`RedisModule_CallReplySetElement`](#RedisModule_CallReplySetElement)\n* [`RedisModule_CallReplyStringPtr`](#RedisModule_CallReplyStringPtr)\n* [`RedisModule_CallReplyType`](#RedisModule_CallReplyType)\n* [`RedisModule_CallReplyVerbatim`](#RedisModule_CallReplyVerbatim)\n* [`RedisModule_Calloc`](#RedisModule_Calloc)\n* [`RedisModule_ChannelAtPosWithFlags`](#RedisModule_ChannelAtPosWithFlags)\n* [`RedisModule_CloseKey`](#RedisModule_CloseKey)\n* [`RedisModule_ClusterCanAccessKeysInSlot`](#RedisModule_ClusterCanAccessKeysInSlot)\n* [`RedisModule_ClusterCanonicalKeyNameInSlot`](#RedisModule_ClusterCanonicalKeyNameInSlot)\n* [`RedisModule_ClusterDisableTrim`](#RedisModule_ClusterDisableTrim)\n* [`RedisModule_ClusterEnableTrim`](#RedisModule_ClusterEnableTrim)\n* [`RedisModule_ClusterFreeSlotRanges`](#RedisModule_ClusterFreeSlotRanges)\n* [`RedisModule_ClusterGetLocalSlotRanges`](#RedisModule_ClusterGetLocalSlotRanges)\n* [`RedisModule_ClusterKeySlot`](#RedisModule_ClusterKeySlot)\n* [`RedisModule_ClusterKeySlotC`](#RedisModule_ClusterKeySlotC)\n* [`RedisModule_ClusterPropagateForSlotMigration`](#RedisModule_ClusterPropagateForSlotMigration)\n* [`RedisModule_CommandFilterArgDelete`](#RedisModule_CommandFilterArgDelete)\n* [`RedisModule_CommandFilterArgGet`](#RedisModule_CommandFilterArgGet)\n* [`RedisModule_CommandFilterArgInsert`](#RedisModule_CommandFilterArgInsert)\n* [`RedisModule_CommandFilterArgReplace`](#RedisModule_CommandFilterArgReplace)\n* [`RedisModule_CommandFilterArgsCount`](#RedisModule_CommandFilterArgsCount)\n* [`RedisModule_CommandFilterGetClientId`](#RedisModule_CommandFilterGetClientId)\n* [`RedisModule_ConfigGet`](#RedisModule_ConfigGet)\n* [`RedisModule_ConfigGetBool`](#RedisModule_ConfigGetBool)\n* [`RedisModule_ConfigGetEnum`](#RedisModule_ConfigGetEnum)\n* [`RedisModule_ConfigGetNumeric`](#RedisModule_ConfigGetNumeric)\n* [`RedisModule_ConfigGetType`](#RedisModule_ConfigGetType)\n* [`RedisModule_ConfigIteratorCreate`](#RedisModule_ConfigIteratorCreate)\n* [`RedisModule_ConfigIteratorNext`](#RedisModule_ConfigIteratorNext)\n* [`RedisModule_ConfigIteratorRelease`](#RedisModule_ConfigIteratorRelease)\n* [`RedisModule_ConfigSet`](#RedisModule_ConfigSet)\n* [`RedisModule_ConfigSetBool`](#RedisModule_ConfigSetBool)\n* [`RedisModule_ConfigSetEnum`](#RedisModule_ConfigSetEnum)\n* [`RedisModule_ConfigSetNumeric`](#RedisModule_ConfigSetNumeric)\n* [`RedisModule_CreateCommand`](#RedisModule_CreateCommand)\n* [`RedisModule_CreateDataType`](#RedisModule_CreateDataType)\n* [`RedisModule_CreateDict`](#RedisModule_CreateDict)\n* [`RedisModule_CreateKeyMetaClass`](#RedisModule_CreateKeyMetaClass)\n* [`RedisModule_CreateModuleUser`](#RedisModule_CreateModuleUser)\n* [`RedisModule_CreateString`](#RedisModule_CreateString)\n* [`RedisModule_CreateStringFromCallReply`](#RedisModule_CreateStringFromCallReply)\n* [`RedisModule_CreateStringFromDouble`](#RedisModule_CreateStringFromDouble)\n* [`RedisModule_CreateStringFromLongDouble`](#RedisModule_CreateStringFromLongDouble)\n* [`RedisModule_CreateStringFromLongLong`](#RedisModule_CreateStringFromLongLong)\n* [`RedisModule_CreateStringFromStreamID`](#RedisModule_CreateStringFromStreamID)\n* [`RedisModule_CreateStringFromString`](#RedisModule_CreateStringFromString)\n* [`RedisModule_CreateStringFromULongLong`](#RedisModule_CreateStringFromULongLong)\n* [`RedisModule_CreateStringPrintf`](#RedisModule_CreateStringPrintf)\n* [`RedisModule_CreateSubcommand`](#RedisModule_CreateSubcommand)\n* [`RedisModule_CreateTimer`](#RedisModule_CreateTimer)\n* [`RedisModule_DbSize`](#RedisModule_DbSize)\n* [`RedisModule_DeauthenticateAndCloseClient`](#RedisModule_DeauthenticateAndCloseClient)\n* [`RedisModule_DefragAlloc`](#RedisModule_DefragAlloc)\n* [`RedisModule_DefragAllocRaw`](#RedisModule_DefragAllocRaw)\n* [`RedisModule_DefragCursorGet`](#RedisModule_DefragCursorGet)\n* [`RedisModule_DefragCursorSet`](#RedisModule_DefragCursorSet)\n* [`RedisModule_DefragFreeRaw`](#RedisModule_DefragFreeRaw)\n* [`RedisModule_DefragRedisModuleDict`](#RedisModule_DefragRedisModuleDict)\n* [`RedisModule_DefragRedisModuleString`](#RedisModule_DefragRedisModuleString)\n* [`RedisModule_DefragShouldStop`](#RedisModule_DefragShouldStop)\n* [`RedisModule_DeleteKey`](#RedisModule_DeleteKey)\n* [`RedisModule_DictCompare`](#RedisModule_DictCompare)\n* [`RedisModule_DictCompareC`](#RedisModule_DictCompareC)\n* [`RedisModule_DictDel`](#RedisModule_DictDel)\n* [`RedisModule_DictDelC`](#RedisModule_DictDelC)\n* [`RedisModule_DictGet`](#RedisModule_DictGet)\n* [`RedisModule_DictGetC`](#RedisModule_DictGetC)\n* [`RedisModule_DictIteratorReseek`](#RedisModule_DictIteratorReseek)\n* [`RedisModule_DictIteratorReseekC`](#RedisModule_DictIteratorReseekC)\n* [`RedisModule_DictIteratorStart`](#RedisModule_DictIteratorStart)\n* [`RedisModule_DictIteratorStartC`](#RedisModule_DictIteratorStartC)\n* [`RedisModule_DictIteratorStop`](#RedisModule_DictIteratorStop)\n* [`RedisModule_DictNext`](#RedisModule_DictNext)\n* [`RedisModule_DictNextC`](#RedisModule_DictNextC)\n* [`RedisModule_DictPrev`](#RedisModule_DictPrev)\n* [`RedisModule_DictPrevC`](#RedisModule_DictPrevC)\n* [`RedisModule_DictReplace`](#RedisModule_DictReplace)\n* [`RedisModule_DictReplaceC`](#RedisModule_DictReplaceC)\n* [`RedisModule_DictSet`](#RedisModule_DictSet)\n* [`RedisModule_DictSetC`](#RedisModule_DictSetC)\n* [`RedisModule_DictSize`](#RedisModule_DictSize)\n* [`RedisModule_DigestAddLongLong`](#RedisModule_DigestAddLongLong)\n* [`RedisModule_DigestAddStringBuffer`](#RedisModule_DigestAddStringBuffer)\n* [`RedisModule_DigestEndSequence`](#RedisModule_DigestEndSequence)\n* [`RedisModule_EmitAOF`](#RedisModule_EmitAOF)\n* [`RedisModule_EventLoopAdd`](#RedisModule_EventLoopAdd)\n* [`RedisModule_EventLoopAddOneShot`](#RedisModule_EventLoopAddOneShot)\n* [`RedisModule_EventLoopDel`](#RedisModule_EventLoopDel)\n* [`RedisModule_ExitFromChild`](#RedisModule_ExitFromChild)\n* [`RedisModule_ExportSharedAPI`](#RedisModule_ExportSharedAPI)\n* [`RedisModule_Fork`](#RedisModule_Fork)\n* [`RedisModule_Free`](#RedisModule_Free)\n* [`RedisModule_FreeCallReply`](#RedisModule_FreeCallReply)\n* [`RedisModule_FreeClusterNodesList`](#RedisModule_FreeClusterNodesList)\n* [`RedisModule_FreeDict`](#RedisModule_FreeDict)\n* [`RedisModule_FreeModuleUser`](#RedisModule_FreeModuleUser)\n* [`RedisModule_FreeServerInfo`](#RedisModule_FreeServerInfo)\n* [`RedisModule_FreeString`](#RedisModule_FreeString)\n* [`RedisModule_FreeThreadSafeContext`](#RedisModule_FreeThreadSafeContext)\n* [`RedisModule_GetAbsExpire`](#RedisModule_GetAbsExpire)\n* [`RedisModule_GetBlockedClientHandle`](#RedisModule_GetBlockedClientHandle)\n* [`RedisModule_GetBlockedClientPrivateData`](#RedisModule_GetBlockedClientPrivateData)\n* [`RedisModule_GetBlockedClientReadyKey`](#RedisModule_GetBlockedClientReadyKey)\n* [`RedisModule_GetClientCertificate`](#RedisModule_GetClientCertificate)\n* [`RedisModule_GetClientId`](#RedisModule_GetClientId)\n* [`RedisModule_GetClientInfoById`](#RedisModule_GetClientInfoById)\n* [`RedisModule_GetClientNameById`](#RedisModule_GetClientNameById)\n* [`RedisModule_GetClientUserNameById`](#RedisModule_GetClientUserNameById)\n* [`RedisModule_GetClusterNodeInfo`](#RedisModule_GetClusterNodeInfo)\n* [`RedisModule_GetClusterNodesList`](#RedisModule_GetClusterNodesList)\n* [`RedisModule_GetClusterSize`](#RedisModule_GetClusterSize)\n* [`RedisModule_GetCommand`](#RedisModule_GetCommand)\n* [`RedisModule_GetCommandKeys`](#RedisModule_GetCommandKeys)\n* [`RedisModule_GetCommandKeysWithFlags`](#RedisModule_GetCommandKeysWithFlags)\n* [`RedisModule_GetContextFlags`](#RedisModule_GetContextFlags)\n* [`RedisModule_GetContextFlagsAll`](#RedisModule_GetContextFlagsAll)\n* [`RedisModule_GetCurrentCommandName`](#RedisModule_GetCurrentCommandName)\n* [`RedisModule_GetCurrentUserName`](#RedisModule_GetCurrentUserName)\n* [`RedisModule_GetDbIdFromDefragCtx`](#RedisModule_GetDbIdFromDefragCtx)\n* [`RedisModule_GetDbIdFromDigest`](#RedisModule_GetDbIdFromDigest)\n* [`RedisModule_GetDbIdFromIO`](#RedisModule_GetDbIdFromIO)\n* [`RedisModule_GetDbIdFromModuleKey`](#RedisModule_GetDbIdFromModuleKey)\n* [`RedisModule_GetDbIdFromOptCtx`](#RedisModule_GetDbIdFromOptCtx)\n* [`RedisModule_GetDetachedThreadSafeContext`](#RedisModule_GetDetachedThreadSafeContext)\n* [`RedisModule_GetExpire`](#RedisModule_GetExpire)\n* [`RedisModule_GetInternalSecret`](#RedisModule_GetInternalSecret)\n* [`RedisModule_GetKeyMeta`](#RedisModule_GetKeyMeta)\n* [`RedisModule_GetKeyNameFromDefragCtx`](#RedisModule_GetKeyNameFromDefragCtx)\n* [`RedisModule_GetKeyNameFromDigest`](#RedisModule_GetKeyNameFromDigest)\n* [`RedisModule_GetKeyNameFromIO`](#RedisModule_GetKeyNameFromIO)\n* [`RedisModule_GetKeyNameFromModuleKey`](#RedisModule_GetKeyNameFromModuleKey)\n* [`RedisModule_GetKeyNameFromOptCtx`](#RedisModule_GetKeyNameFromOptCtx)\n* [`RedisModule_GetKeyspaceNotificationFlagsAll`](#RedisModule_GetKeyspaceNotificationFlagsAll)\n* [`RedisModule_GetLFU`](#RedisModule_GetLFU)\n* [`RedisModule_GetLRU`](#RedisModule_GetLRU)\n* [`RedisModule_GetModuleOptionsAll`](#RedisModule_GetModuleOptionsAll)\n* [`RedisModule_GetModuleUserACLString`](#RedisModule_GetModuleUserACLString)\n* [`RedisModule_GetModuleUserFromUserName`](#RedisModule_GetModuleUserFromUserName)\n* [`RedisModule_GetMyClusterID`](#RedisModule_GetMyClusterID)\n* [`RedisModule_GetNotifyKeyspaceEvents`](#RedisModule_GetNotifyKeyspaceEvents)\n* [`RedisModule_GetOpenKeyModesAll`](#RedisModule_GetOpenKeyModesAll)\n* [`RedisModule_GetRandomBytes`](#RedisModule_GetRandomBytes)\n* [`RedisModule_GetRandomHexChars`](#RedisModule_GetRandomHexChars)\n* [`RedisModule_GetSelectedDb`](#RedisModule_GetSelectedDb)\n* [`RedisModule_GetServerInfo`](#RedisModule_GetServerInfo)\n* [`RedisModule_GetServerVersion`](#RedisModule_GetServerVersion)\n* [`RedisModule_GetSharedAPI`](#RedisModule_GetSharedAPI)\n* [`RedisModule_GetThreadSafeContext`](#RedisModule_GetThreadSafeContext)\n* [`RedisModule_GetTimerInfo`](#RedisModule_GetTimerInfo)\n* [`RedisModule_GetToDbIdFromOptCtx`](#RedisModule_GetToDbIdFromOptCtx)\n* [`RedisModule_GetToKeyNameFromOptCtx`](#RedisModule_GetToKeyNameFromOptCtx)\n* [`RedisModule_GetTypeMethodVersion`](#RedisModule_GetTypeMethodVersion)\n* [`RedisModule_GetUsedMemoryRatio`](#RedisModule_GetUsedMemoryRatio)\n* [`RedisModule_HashFieldMinExpire`](#RedisModule_HashFieldMinExpire)\n* [`RedisModule_HashGet`](#RedisModule_HashGet)\n* [`RedisModule_HashSet`](#RedisModule_HashSet)\n* [`RedisModule_HoldString`](#RedisModule_HoldString)\n* [`RedisModule_InfoAddFieldCString`](#RedisModule_InfoAddFieldCString)\n* [`RedisModule_InfoAddFieldDouble`](#RedisModule_InfoAddFieldDouble)\n* [`RedisModule_InfoAddFieldLongLong`](#RedisModule_InfoAddFieldLongLong)\n* [`RedisModule_InfoAddFieldString`](#RedisModule_InfoAddFieldString)\n* [`RedisModule_InfoAddFieldULongLong`](#RedisModule_InfoAddFieldULongLong)\n* [`RedisModule_InfoAddSection`](#RedisModule_InfoAddSection)\n* [`RedisModule_InfoBeginDictField`](#RedisModule_InfoBeginDictField)\n* [`RedisModule_InfoEndDictField`](#RedisModule_InfoEndDictField)\n* [`RedisModule_IsBlockedReplyRequest`](#RedisModule_IsBlockedReplyRequest)\n* [`RedisModule_IsBlockedTimeoutRequest`](#RedisModule_IsBlockedTimeoutRequest)\n* [`RedisModule_IsChannelsPositionRequest`](#RedisModule_IsChannelsPositionRequest)\n* [`RedisModule_IsIOError`](#RedisModule_IsIOError)\n* [`RedisModule_IsKeysPositionRequest`](#RedisModule_IsKeysPositionRequest)\n* [`RedisModule_IsModuleNameBusy`](#RedisModule_IsModuleNameBusy)\n* [`RedisModule_IsSubEventSupported`](#RedisModule_IsSubEventSupported)\n* [`RedisModule_KeyAtPos`](#RedisModule_KeyAtPos)\n* [`RedisModule_KeyAtPosWithFlags`](#RedisModule_KeyAtPosWithFlags)\n* [`RedisModule_KeyExists`](#RedisModule_KeyExists)\n* [`RedisModule_KeyType`](#RedisModule_KeyType)\n* [`RedisModule_KillForkChild`](#RedisModule_KillForkChild)\n* [`RedisModule_LatencyAddSample`](#RedisModule_LatencyAddSample)\n* [`RedisModule_ListDelete`](#RedisModule_ListDelete)\n* [`RedisModule_ListGet`](#RedisModule_ListGet)\n* [`RedisModule_ListInsert`](#RedisModule_ListInsert)\n* [`RedisModule_ListPop`](#RedisModule_ListPop)\n* [`RedisModule_ListPush`](#RedisModule_ListPush)\n* [`RedisModule_ListSet`](#RedisModule_ListSet)\n* [`RedisModule_LoadConfigs`](#RedisModule_LoadConfigs)\n* [`RedisModule_LoadDataTypeFromString`](#RedisModule_LoadDataTypeFromString)\n* [`RedisModule_LoadDataTypeFromStringEncver`](#RedisModule_LoadDataTypeFromStringEncver)\n* [`RedisModule_LoadDefaultConfigs`](#RedisModule_LoadDefaultConfigs)\n* [`RedisModule_LoadDouble`](#RedisModule_LoadDouble)\n* [`RedisModule_LoadFloat`](#RedisModule_LoadFloat)\n* [`RedisModule_LoadLongDouble`](#RedisModule_LoadLongDouble)\n* [`RedisModule_LoadSigned`](#RedisModule_LoadSigned)\n* [`RedisModule_LoadString`](#RedisModule_LoadString)\n* [`RedisModule_LoadStringBuffer`](#RedisModule_LoadStringBuffer)\n* [`RedisModule_LoadUnsigned`](#RedisModule_LoadUnsigned)\n* [`RedisModule_Log`](#RedisModule_Log)\n* [`RedisModule_LogIOError`](#RedisModule_LogIOError)\n* [`RedisModule_MallocSize`](#RedisModule_MallocSize)\n* [`RedisModule_MallocSizeDict`](#RedisModule_MallocSizeDict)\n* [`RedisModule_MallocSizeString`](#RedisModule_MallocSizeString)\n* [`RedisModule_MallocUsableSize`](#RedisModule_MallocUsableSize)\n* [`RedisModule_Microseconds`](#RedisModule_Microseconds)\n* [`RedisModule_Milliseconds`](#RedisModule_Milliseconds)\n* [`RedisModule_ModuleTypeGetType`](#RedisModule_ModuleTypeGetType)\n* [`RedisModule_ModuleTypeGetValue`](#RedisModule_ModuleTypeGetValue)\n* [`RedisModule_ModuleTypeReplaceValue`](#RedisModule_ModuleTypeReplaceValue)\n* [`RedisModule_ModuleTypeSetValue`](#RedisModule_ModuleTypeSetValue)\n* [`RedisModule_MonotonicMicroseconds`](#RedisModule_MonotonicMicroseconds)\n* [`RedisModule_NotifyKeyspaceEvent`](#RedisModule_NotifyKeyspaceEvent)\n* [`RedisModule_OpenKey`](#RedisModule_OpenKey)\n* [`RedisModule_PoolAlloc`](#RedisModule_PoolAlloc)\n* [`RedisModule_PublishMessage`](#RedisModule_PublishMessage)\n* [`RedisModule_PublishMessageShard`](#RedisModule_PublishMessageShard)\n* [`RedisModule_RandomKey`](#RedisModule_RandomKey)\n* [`RedisModule_RdbLoad`](#RedisModule_RdbLoad)\n* [`RedisModule_RdbSave`](#RedisModule_RdbSave)\n* [`RedisModule_RdbStreamCreateFromFile`](#RedisModule_RdbStreamCreateFromFile)\n* [`RedisModule_RdbStreamFree`](#RedisModule_RdbStreamFree)\n* [`RedisModule_Realloc`](#RedisModule_Realloc)\n* [`RedisModule_RedactClientCommandArgument`](#RedisModule_RedactClientCommandArgument)\n* [`RedisModule_RegisterAuthCallback`](#RedisModule_RegisterAuthCallback)\n* [`RedisModule_RegisterBoolConfig`](#RedisModule_RegisterBoolConfig)\n* [`RedisModule_RegisterClusterMessageReceiver`](#RedisModule_RegisterClusterMessageReceiver)\n* [`RedisModule_RegisterCommandFilter`](#RedisModule_RegisterCommandFilter)\n* [`RedisModule_RegisterDefragCallbacks`](#RedisModule_RegisterDefragCallbacks)\n* [`RedisModule_RegisterDefragFunc`](#RedisModule_RegisterDefragFunc)\n* [`RedisModule_RegisterDefragFunc2`](#RedisModule_RegisterDefragFunc2)\n* [`RedisModule_RegisterEnumConfig`](#RedisModule_RegisterEnumConfig)\n* [`RedisModule_RegisterInfoFunc`](#RedisModule_RegisterInfoFunc)\n* [`RedisModule_RegisterNumericConfig`](#RedisModule_RegisterNumericConfig)\n* [`RedisModule_RegisterStringConfig`](#RedisModule_RegisterStringConfig)\n* [`RedisModule_ReleaseKeyMetaClass`](#RedisModule_ReleaseKeyMetaClass)\n* [`RedisModule_Replicate`](#RedisModule_Replicate)\n* [`RedisModule_ReplicateVerbatim`](#RedisModule_ReplicateVerbatim)\n* [`RedisModule_ReplySetArrayLength`](#RedisModule_ReplySetArrayLength)\n* [`RedisModule_ReplySetAttributeLength`](#RedisModule_ReplySetAttributeLength)\n* [`RedisModule_ReplySetMapLength`](#RedisModule_ReplySetMapLength)\n* [`RedisModule_ReplySetSetLength`](#RedisModule_ReplySetSetLength)\n* [`RedisModule_ReplyWithArray`](#RedisModule_ReplyWithArray)\n* [`RedisModule_ReplyWithAttribute`](#RedisModule_ReplyWithAttribute)\n* [`RedisModule_ReplyWithBigNumber`](#RedisModule_ReplyWithBigNumber)\n* [`RedisModule_ReplyWithBool`](#RedisModule_ReplyWithBool)\n* [`RedisModule_ReplyWithCString`](#RedisModule_ReplyWithCString)\n* [`RedisModule_ReplyWithCallReply`](#RedisModule_ReplyWithCallReply)\n* [`RedisModule_ReplyWithDouble`](#RedisModule_ReplyWithDouble)\n* [`RedisModule_ReplyWithEmptyArray`](#RedisModule_ReplyWithEmptyArray)\n* [`RedisModule_ReplyWithEmptyString`](#RedisModule_ReplyWithEmptyString)\n* [`RedisModule_ReplyWithError`](#RedisModule_ReplyWithError)\n* [`RedisModule_ReplyWithErrorFormat`](#RedisModule_ReplyWithErrorFormat)\n* [`RedisModule_ReplyWithLongDouble`](#RedisModule_ReplyWithLongDouble)\n* [`RedisModule_ReplyWithLongLong`](#RedisModule_ReplyWithLongLong)\n* [`RedisModule_ReplyWithMap`](#RedisModule_ReplyWithMap)\n* [`RedisModule_ReplyWithNull`](#RedisModule_ReplyWithNull)\n* [`RedisModule_ReplyWithNullArray`](#RedisModule_ReplyWithNullArray)\n* [`RedisModule_ReplyWithSet`](#RedisModule_ReplyWithSet)\n* [`RedisModule_ReplyWithSimpleString`](#RedisModule_ReplyWithSimpleString)\n* [`RedisModule_ReplyWithString`](#RedisModule_ReplyWithString)\n* [`RedisModule_ReplyWithStringBuffer`](#RedisModule_ReplyWithStringBuffer)\n* [`RedisModule_ReplyWithVerbatimString`](#RedisModule_ReplyWithVerbatimString)\n* [`RedisModule_ReplyWithVerbatimStringType`](#RedisModule_ReplyWithVerbatimStringType)\n* [`RedisModule_ResetDataset`](#RedisModule_ResetDataset)\n* [`RedisModule_RetainString`](#RedisModule_RetainString)\n* [`RedisModule_SaveDataTypeToString`](#RedisModule_SaveDataTypeToString)\n* [`RedisModule_SaveDouble`](#RedisModule_SaveDouble)\n* [`RedisModule_SaveFloat`](#RedisModule_SaveFloat)\n* [`RedisModule_SaveLongDouble`](#RedisModule_SaveLongDouble)\n* [`RedisModule_SaveSigned`](#RedisModule_SaveSigned)\n* [`RedisModule_SaveString`](#RedisModule_SaveString)\n* [`RedisModule_SaveStringBuffer`](#RedisModule_SaveStringBuffer)\n* [`RedisModule_SaveUnsigned`](#RedisModule_SaveUnsigned)\n* [`RedisModule_Scan`](#RedisModule_Scan)\n* [`RedisModule_ScanCursorCreate`](#RedisModule_ScanCursorCreate)\n* [`RedisModule_ScanCursorDestroy`](#RedisModule_ScanCursorDestroy)\n* [`RedisModule_ScanCursorRestart`](#RedisModule_ScanCursorRestart)\n* [`RedisModule_ScanKey`](#RedisModule_ScanKey)\n* [`RedisModule_SelectDb`](#RedisModule_SelectDb)\n* [`RedisModule_SendChildHeartbeat`](#RedisModule_SendChildHeartbeat)\n* [`RedisModule_SendClusterMessage`](#RedisModule_SendClusterMessage)\n* [`RedisModule_ServerInfoGetField`](#RedisModule_ServerInfoGetField)\n* [`RedisModule_ServerInfoGetFieldC`](#RedisModule_ServerInfoGetFieldC)\n* [`RedisModule_ServerInfoGetFieldDouble`](#RedisModule_ServerInfoGetFieldDouble)\n* [`RedisModule_ServerInfoGetFieldSigned`](#RedisModule_ServerInfoGetFieldSigned)\n* [`RedisModule_ServerInfoGetFieldUnsigned`](#RedisModule_ServerInfoGetFieldUnsigned)\n* [`RedisModule_SetAbsExpire`](#RedisModule_SetAbsExpire)\n* [`RedisModule_SetClientNameById`](#RedisModule_SetClientNameById)\n* [`RedisModule_SetClusterFlags`](#RedisModule_SetClusterFlags)\n* [`RedisModule_SetCommandACLCategories`](#RedisModule_SetCommandACLCategories)\n* [`RedisModule_SetCommandInfo`](#RedisModule_SetCommandInfo)\n* [`RedisModule_SetContextUser`](#RedisModule_SetContextUser)\n* [`RedisModule_SetDisconnectCallback`](#RedisModule_SetDisconnectCallback)\n* [`RedisModule_SetExpire`](#RedisModule_SetExpire)\n* [`RedisModule_SetKeyMeta`](#RedisModule_SetKeyMeta)\n* [`RedisModule_SetLFU`](#RedisModule_SetLFU)\n* [`RedisModule_SetLRU`](#RedisModule_SetLRU)\n* [`RedisModule_SetModuleOptions`](#RedisModule_SetModuleOptions)\n* [`RedisModule_SetModuleUserACL`](#RedisModule_SetModuleUserACL)\n* [`RedisModule_SetModuleUserACLString`](#RedisModule_SetModuleUserACLString)\n* [`RedisModule_SignalKeyAsReady`](#RedisModule_SignalKeyAsReady)\n* [`RedisModule_SignalModifiedKey`](#RedisModule_SignalModifiedKey)\n* [`RedisModule_StopTimer`](#RedisModule_StopTimer)\n* [`RedisModule_Strdup`](#RedisModule_Strdup)\n* [`RedisModule_StreamAdd`](#RedisModule_StreamAdd)\n* [`RedisModule_StreamDelete`](#RedisModule_StreamDelete)\n* [`RedisModule_StreamIteratorDelete`](#RedisModule_StreamIteratorDelete)\n* [`RedisModule_StreamIteratorNextField`](#RedisModule_StreamIteratorNextField)\n* [`RedisModule_StreamIteratorNextID`](#RedisModule_StreamIteratorNextID)\n* [`RedisModule_StreamIteratorStart`](#RedisModule_StreamIteratorStart)\n* [`RedisModule_StreamIteratorStop`](#RedisModule_StreamIteratorStop)\n* [`RedisModule_StreamTrimByID`](#RedisModule_StreamTrimByID)\n* [`RedisModule_StreamTrimByLength`](#RedisModule_StreamTrimByLength)\n* [`RedisModule_StringAppendBuffer`](#RedisModule_StringAppendBuffer)\n* [`RedisModule_StringCompare`](#RedisModule_StringCompare)\n* [`RedisModule_StringDMA`](#RedisModule_StringDMA)\n* [`RedisModule_StringPtrLen`](#RedisModule_StringPtrLen)\n* [`RedisModule_StringSet`](#RedisModule_StringSet)\n* [`RedisModule_StringToDouble`](#RedisModule_StringToDouble)\n* [`RedisModule_StringToLongDouble`](#RedisModule_StringToLongDouble)\n* [`RedisModule_StringToLongLong`](#RedisModule_StringToLongLong)\n* [`RedisModule_StringToStreamID`](#RedisModule_StringToStreamID)\n* [`RedisModule_StringToULongLong`](#RedisModule_StringToULongLong)\n* [`RedisModule_StringTruncate`](#RedisModule_StringTruncate)\n* [`RedisModule_SubscribeToKeyspaceEvents`](#RedisModule_SubscribeToKeyspaceEvents)\n* [`RedisModule_SubscribeToServerEvent`](#RedisModule_SubscribeToServerEvent)\n* [`RedisModule_ThreadSafeContextLock`](#RedisModule_ThreadSafeContextLock)\n* [`RedisModule_ThreadSafeContextTryLock`](#RedisModule_ThreadSafeContextTryLock)\n* [`RedisModule_ThreadSafeContextUnlock`](#RedisModule_ThreadSafeContextUnlock)\n* [`RedisModule_TrimStringAllocation`](#RedisModule_TrimStringAllocation)\n* [`RedisModule_TryAlloc`](#RedisModule_TryAlloc)\n* [`RedisModule_TryCalloc`](#RedisModule_TryCalloc)\n* [`RedisModule_TryRealloc`](#RedisModule_TryRealloc)\n* [`RedisModule_UnblockClient`](#RedisModule_UnblockClient)\n* [`RedisModule_UnlinkKey`](#RedisModule_UnlinkKey)\n* [`RedisModule_UnregisterCommandFilter`](#RedisModule_UnregisterCommandFilter)\n* [`RedisModule_UnsubscribeFromKeyspaceEvents`](#RedisModule_UnsubscribeFromKeyspaceEvents)\n* [`RedisModule_ValueLength`](#RedisModule_ValueLength)\n* [`RedisModule_WrongArity`](#RedisModule_WrongArity)\n* [`RedisModule_Yield`](#RedisModule_Yield)\n* [`RedisModule_ZsetAdd`](#RedisModule_ZsetAdd)\n* [`RedisModule_ZsetFirstInLexRange`](#RedisModule_ZsetFirstInLexRange)\n* [`RedisModule_ZsetFirstInScoreRange`](#RedisModule_ZsetFirstInScoreRange)\n* [`RedisModule_ZsetIncrby`](#RedisModule_ZsetIncrby)\n* [`RedisModule_ZsetLastInLexRange`](#RedisModule_ZsetLastInLexRange)\n* [`RedisModule_ZsetLastInScoreRange`](#RedisModule_ZsetLastInScoreRange)\n* [`RedisModule_ZsetRangeCurrentElement`](#RedisModule_ZsetRangeCurrentElement)\n* [`RedisModule_ZsetRangeEndReached`](#RedisModule_ZsetRangeEndReached)\n* [`RedisModule_ZsetRangeNext`](#RedisModule_ZsetRangeNext)\n* [`RedisModule_ZsetRangePrev`](#RedisModule_ZsetRangePrev)\n* [`RedisModule_ZsetRangeStop`](#RedisModule_ZsetRangeStop)\n* [`RedisModule_ZsetRem`](#RedisModule_ZsetRem)\n* [`RedisModule_ZsetScore`](#RedisModule_ZsetScore)\n* [`RedisModule__Assert`](#RedisModule__Assert)"
    }
  ],
  "examples": [
    {
      "id": "redismodule-configiteratorcreate-ex0",
      "language": "plaintext",
      "code": "// Below is same as [`RedisModule_ConfigIteratorCreate`](#RedisModule_ConfigIteratorCreate)(ctx, NULL)\n`RedisModuleConfigIterator` *iter = [`RedisModule_ConfigIteratorCreate`](#RedisModule_ConfigIteratorCreate)(ctx, \"*\");\nconst char *config_name = NULL;\nwhile ((`config_name` = [`RedisModule_ConfigIteratorNext`](#RedisModule_ConfigIteratorNext)(iter)) != NULL) {\n    RedisModuleString *value = NULL;\n    if (RedisModule_ConfigGet(ctx, config_name, &value) == REDISMODULE_OK) {\n        // Do something with `value`...\n        RedisModule_FreeString(ctx, value);\n    }\n}\n[`RedisModule_ConfigIteratorRelease`](#RedisModule_ConfigIteratorRelease)(ctx, iter);\n\n// Or optionally one can check the type to get the config value directly\n// via the appropriate API in case performance is of consideration\niter = [`RedisModule_ConfigIteratorCreate`](#RedisModule_ConfigIteratorCreate)(ctx, \"*\");\nwhile ((`config_name` = [`RedisModule_ConfigIteratorNext`](#RedisModule_ConfigIteratorNext)(iter)) != NULL) {\n    RedisModuleConfigType type = RedisModule_ConfigGetType(config_name);\n    if (type == REDISMODULE_CONFIG_TYPE_STRING) {\n        RedisModuleString *value;\n        RedisModule_ConfigGet(ctx, config_name, &value);\n        // Do something with `value`...\n        RedisModule_FreeString(ctx, value);\n    } if (type == REDISMODULE_CONFIG_TYPE_NUMERIC) {\n        long long value;\n        RedisModule_ConfigGetNumeric(ctx, config_name, &value);\n        // Do something with `value`...\n    } else if (type == REDISMODULE_CONFIG_TYPE_BOOL) {\n        int value;\n        RedisModule_ConfigGetBool(ctx, config_name, &value);\n        // Do something with `value`...\n    } else if (type == REDISMODULE_CONFIG_TYPE_ENUM) {\n        RedisModuleString *value;\n        RedisModule_ConfigGetEnum(ctx, config_name, &value);\n        // Do something with `value`...\n        RedisModule_Free(value);\n    }\n}\n[`RedisModule_ConfigIteratorRelease`](#RedisModule_ConfigIteratorRelease)(ctx, iter);",
      "section_id": "redismodule-configiteratorcreate"
    }
  ]
}
