// SPDX-FileCopyrightText: 2024 Redict Contributors // SPDX-FileCopyrightText: 2024 Salvatore Sanfilippo // // SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: LGPL-3.0-only #include "redictmodule.h" #define UNUSED(V) ((void) V) int cmd_xadd(RedictModuleCtx *ctx, RedictModuleString **argv, int argc) { UNUSED(argv); UNUSED(argc); RedictModule_ReplyWithSimpleString(ctx, "OK"); return REDICTMODULE_OK; } int RedictModule_OnLoad(RedictModuleCtx *ctx, RedictModuleString **argv, int argc) { REDICTMODULE_NOT_USED(argv); REDICTMODULE_NOT_USED(argc); if (RedictModule_Init(ctx, "cmdintrospection", 1, REDICTMODULE_APIVER_1) == REDICTMODULE_ERR) return REDICTMODULE_ERR; if (RedictModule_CreateCommand(ctx,"cmdintrospection.xadd",cmd_xadd,"write deny-oom random fast",0,0,0) == REDICTMODULE_ERR) return REDICTMODULE_ERR; RedictModuleCommand *xadd = RedictModule_GetCommand(ctx,"cmdintrospection.xadd"); RedictModuleCommandInfo info = { .version = REDICTMODULE_COMMAND_INFO_VERSION, .arity = -5, .summary = "Appends a new message to a stream. Creates the key if it doesn't exist.", .since = "5.0.0", .complexity = "O(1) when adding a new entry, O(N) when trimming where N being the number of entries evicted.", .tips = "nondeterministic_output", .history = (RedictModuleCommandHistoryEntry[]){ /* NOTE: All versions specified should be the module's versions, not * Redict'! We use Redict versions in this example for the purpose of * testing (comparing the output with the output of the vanilla * XADD). */ {"6.2.0", "Added the `NOMKSTREAM` option, `MINID` trimming strategy and the `LIMIT` option."}, {"7.0.0", "Added support for the `-*` explicit ID form."}, {0} }, .key_specs = (RedictModuleCommandKeySpec[]){ { .notes = "UPDATE instead of INSERT because of the optional trimming feature", .flags = REDICTMODULE_CMD_KEY_RW | REDICTMODULE_CMD_KEY_UPDATE, .begin_search_type = REDICTMODULE_KSPEC_BS_INDEX, .bs.index.pos = 1, .find_keys_type = REDICTMODULE_KSPEC_FK_RANGE, .fk.range = {0,1,0} }, {0} }, .args = (RedictModuleCommandArg[]){ { .name = "key", .type = REDICTMODULE_ARG_TYPE_KEY, .key_spec_index = 0 }, { .name = "nomkstream", .type = REDICTMODULE_ARG_TYPE_PURE_TOKEN, .token = "NOMKSTREAM", .since = "6.2.0", .flags = REDICTMODULE_CMD_ARG_OPTIONAL }, { .name = "trim", .type = REDICTMODULE_ARG_TYPE_BLOCK, .flags = REDICTMODULE_CMD_ARG_OPTIONAL, .subargs = (RedictModuleCommandArg[]){ { .name = "strategy", .type = REDICTMODULE_ARG_TYPE_ONEOF, .subargs = (RedictModuleCommandArg[]){ { .name = "maxlen", .type = REDICTMODULE_ARG_TYPE_PURE_TOKEN, .token = "MAXLEN", }, { .name = "minid", .type = REDICTMODULE_ARG_TYPE_PURE_TOKEN, .token = "MINID", .since = "6.2.0", }, {0} } }, { .name = "operator", .type = REDICTMODULE_ARG_TYPE_ONEOF, .flags = REDICTMODULE_CMD_ARG_OPTIONAL, .subargs = (RedictModuleCommandArg[]){ { .name = "equal", .type = REDICTMODULE_ARG_TYPE_PURE_TOKEN, .token = "=" }, { .name = "approximately", .type = REDICTMODULE_ARG_TYPE_PURE_TOKEN, .token = "~" }, {0} } }, { .name = "threshold", .type = REDICTMODULE_ARG_TYPE_STRING, .display_text = "threshold" /* Just for coverage, doesn't have a visible effect */ }, { .name = "count", .type = REDICTMODULE_ARG_TYPE_INTEGER, .token = "LIMIT", .since = "6.2.0", .flags = REDICTMODULE_CMD_ARG_OPTIONAL }, {0} } }, { .name = "id-selector", .type = REDICTMODULE_ARG_TYPE_ONEOF, .subargs = (RedictModuleCommandArg[]){ { .name = "auto-id", .type = REDICTMODULE_ARG_TYPE_PURE_TOKEN, .token = "*" }, { .name = "id", .type = REDICTMODULE_ARG_TYPE_STRING, }, {0} } }, { .name = "data", .type = REDICTMODULE_ARG_TYPE_BLOCK, .flags = REDICTMODULE_CMD_ARG_MULTIPLE, .subargs = (RedictModuleCommandArg[]){ { .name = "field", .type = REDICTMODULE_ARG_TYPE_STRING, }, { .name = "value", .type = REDICTMODULE_ARG_TYPE_STRING, }, {0} } }, {0} } }; if (RedictModule_SetCommandInfo(xadd, &info) == REDICTMODULE_ERR) return REDICTMODULE_ERR; return REDICTMODULE_OK; }