From 4abbae87c946e475ca335d804818e6fad1e672fb Mon Sep 17 00:00:00 2001 From: Sergey Kolosov Date: Fri, 7 Feb 2025 14:14:32 -0800 Subject: [PATCH] Implement: CLUSTER REPLICATE NO ONE --- src/cluster_legacy.c | 24 ++++++++++++++++++++++-- src/commands.def | 16 ++++++++++++++-- src/commands/cluster-replicate.json | 28 +++++++++++++++++++++++++--- 3 files changed, 61 insertions(+), 7 deletions(-) diff --git a/src/cluster_legacy.c b/src/cluster_legacy.c index 26aea15bbd..078cdbc048 100644 --- a/src/cluster_legacy.c +++ b/src/cluster_legacy.c @@ -7029,9 +7029,29 @@ int clusterCommandSpecial(client *c) { clusterDelNode(n); clusterDoBeforeSleep(CLUSTER_TODO_UPDATE_STATE | CLUSTER_TODO_SAVE_CONFIG); addReply(c, shared.ok); - } else if (!strcasecmp(c->argv[1]->ptr, "replicate") && c->argc == 3) { - /* CLUSTER REPLICATE */ + } else if (!strcasecmp(c->argv[1]->ptr, "replicate") && (c->argc == 3 || c->argc == 4)) { + /* CLUSTER REPLICATE ( | NO ONE)*/ /* Lookup the specified node in our table. */ + if (c->argc == 4) { + if (0 != strcasecmp(c->argv[2]->ptr, "NO") || 0 != strcasecmp(c->argv[3]->ptr, "ONE")) { + addReplySubcommandSyntaxError(c); + return 1; + } + if (nodeIsPrimary(myself)) { + addReply(c, shared.ok); + return 1; + } + serverLog(LL_NOTICE, "Stop replication and turning myself into empty primary."); + clusterSetNodeAsPrimary(myself); + clusterPromoteSelfToPrimary(); + int empty_db_flags = server.repl_replica_lazy_flush ? EMPTYDB_ASYNC : EMPTYDB_NO_FLAGS; + emptyData(-1, empty_db_flags, NULL); + /* Reset manual failover state. */ + resetManualFailover(); + clusterDoBeforeSleep(CLUSTER_TODO_UPDATE_STATE | CLUSTER_TODO_SAVE_CONFIG | CLUSTER_TODO_BROADCAST_ALL); + addReply(c, shared.ok); + return 1; + } clusterNode *n = clusterLookupNode(c->argv[2]->ptr, sdslen(c->argv[2]->ptr)); if (!n) { addReplyErrorFormat(c, "Unknown node %s", (char *)c->argv[2]->ptr); diff --git a/src/commands.def b/src/commands.def index 613eb16c9b..45085c6f7f 100644 --- a/src/commands.def +++ b/src/commands.def @@ -781,9 +781,21 @@ struct COMMAND_ARG CLUSTER_REPLICAS_Args[] = { #define CLUSTER_REPLICATE_Keyspecs NULL #endif +/* CLUSTER REPLICATE args no_one argument table */ +struct COMMAND_ARG CLUSTER_REPLICATE_args_no_one_Subargs[] = { +{MAKE_ARG("no",ARG_TYPE_PURE_TOKEN,-1,"NO",NULL,NULL,CMD_ARG_NONE,0,NULL)}, +{MAKE_ARG("one",ARG_TYPE_PURE_TOKEN,-1,"ONE",NULL,NULL,CMD_ARG_NONE,0,NULL)}, +}; + +/* CLUSTER REPLICATE args argument table */ +struct COMMAND_ARG CLUSTER_REPLICATE_args_Subargs[] = { +{MAKE_ARG("node-id",ARG_TYPE_STRING,-1,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)}, +{MAKE_ARG("no-one",ARG_TYPE_BLOCK,-1,NULL,NULL,NULL,CMD_ARG_NONE,2,NULL),.subargs=CLUSTER_REPLICATE_args_no_one_Subargs}, +}; + /* CLUSTER REPLICATE argument table */ struct COMMAND_ARG CLUSTER_REPLICATE_Args[] = { -{MAKE_ARG("node-id",ARG_TYPE_STRING,-1,NULL,NULL,NULL,CMD_ARG_NONE,0,NULL)}, +{MAKE_ARG("args",ARG_TYPE_ONEOF,-1,NULL,NULL,NULL,CMD_ARG_NONE,2,NULL),.subargs=CLUSTER_REPLICATE_args_Subargs}, }; /********** CLUSTER RESET ********************/ @@ -1024,7 +1036,7 @@ struct COMMAND_STRUCT CLUSTER_Subcommands[] = { {MAKE_CMD("myshardid","Returns the shard ID of a node.","O(1)","7.2.0",CMD_DOC_NONE,NULL,NULL,"cluster",COMMAND_GROUP_CLUSTER,CLUSTER_MYSHARDID_History,0,CLUSTER_MYSHARDID_Tips,1,clusterCommand,2,CMD_LOADING|CMD_STALE,0,CLUSTER_MYSHARDID_Keyspecs,0,NULL,0)}, {MAKE_CMD("nodes","Returns the cluster configuration for a node.","O(N) where N is the total number of Cluster nodes","3.0.0",CMD_DOC_NONE,NULL,NULL,"cluster",COMMAND_GROUP_CLUSTER,CLUSTER_NODES_History,0,CLUSTER_NODES_Tips,1,clusterCommand,2,CMD_LOADING|CMD_STALE,0,CLUSTER_NODES_Keyspecs,0,NULL,0)}, {MAKE_CMD("replicas","Lists the replica nodes of a primary node.","O(N) where N is the number of replicas.","5.0.0",CMD_DOC_NONE,NULL,NULL,"cluster",COMMAND_GROUP_CLUSTER,CLUSTER_REPLICAS_History,0,CLUSTER_REPLICAS_Tips,1,clusterCommand,3,CMD_ADMIN|CMD_STALE,0,CLUSTER_REPLICAS_Keyspecs,0,NULL,1),.args=CLUSTER_REPLICAS_Args}, -{MAKE_CMD("replicate","Configure a node as replica of a primary node.","O(1)","3.0.0",CMD_DOC_NONE,NULL,NULL,"cluster",COMMAND_GROUP_CLUSTER,CLUSTER_REPLICATE_History,0,CLUSTER_REPLICATE_Tips,0,clusterCommand,3,CMD_NO_ASYNC_LOADING|CMD_ADMIN|CMD_STALE,0,CLUSTER_REPLICATE_Keyspecs,0,NULL,1),.args=CLUSTER_REPLICATE_Args}, +{MAKE_CMD("replicate","Configure a node as replica of a primary node or detaches replica from primary.","O(1)","3.0.0",CMD_DOC_NONE,NULL,NULL,"cluster",COMMAND_GROUP_CLUSTER,CLUSTER_REPLICATE_History,0,CLUSTER_REPLICATE_Tips,0,clusterCommand,3,CMD_NO_ASYNC_LOADING|CMD_ADMIN|CMD_STALE,0,CLUSTER_REPLICATE_Keyspecs,0,NULL,1),.args=CLUSTER_REPLICATE_Args}, {MAKE_CMD("reset","Resets a node.","O(N) where N is the number of known nodes. The command may execute a FLUSHALL as a side effect.","3.0.0",CMD_DOC_NONE,NULL,NULL,"cluster",COMMAND_GROUP_CLUSTER,CLUSTER_RESET_History,0,CLUSTER_RESET_Tips,0,clusterCommand,-2,CMD_ADMIN|CMD_STALE|CMD_NOSCRIPT,0,CLUSTER_RESET_Keyspecs,0,NULL,1),.args=CLUSTER_RESET_Args}, {MAKE_CMD("saveconfig","Forces a node to save the cluster configuration to disk.","O(1)","3.0.0",CMD_DOC_NONE,NULL,NULL,"cluster",COMMAND_GROUP_CLUSTER,CLUSTER_SAVECONFIG_History,0,CLUSTER_SAVECONFIG_Tips,0,clusterCommand,2,CMD_NO_ASYNC_LOADING|CMD_ADMIN|CMD_STALE,0,CLUSTER_SAVECONFIG_Keyspecs,0,NULL,0)}, {MAKE_CMD("set-config-epoch","Sets the configuration epoch for a new node.","O(1)","3.0.0",CMD_DOC_NONE,NULL,NULL,"cluster",COMMAND_GROUP_CLUSTER,CLUSTER_SET_CONFIG_EPOCH_History,0,CLUSTER_SET_CONFIG_EPOCH_Tips,0,clusterCommand,3,CMD_NO_ASYNC_LOADING|CMD_ADMIN|CMD_STALE,0,CLUSTER_SET_CONFIG_EPOCH_Keyspecs,0,NULL,1),.args=CLUSTER_SET_CONFIG_EPOCH_Args}, diff --git a/src/commands/cluster-replicate.json b/src/commands/cluster-replicate.json index 857a8022b8..1ae8936ecb 100644 --- a/src/commands/cluster-replicate.json +++ b/src/commands/cluster-replicate.json @@ -1,6 +1,6 @@ { "REPLICATE": { - "summary": "Configure a node as replica of a primary node.", + "summary": "Configure a node as replica of a primary node or detaches replica from primary.", "complexity": "O(1)", "group": "cluster", "since": "3.0.0", @@ -14,8 +14,30 @@ ], "arguments": [ { - "name": "node-id", - "type": "string" + "name": "args", + "type": "oneof", + "arguments": [ + { + "name": "node-id", + "type": "string" + }, + { + "name": "no-one", + "type": "block", + "arguments": [ + { + "name": "no", + "type": "pure-token", + "token": "NO" + }, + { + "name": "one", + "type": "pure-token", + "token": "ONE" + } + ] + } + ] } ], "reply_schema": {