You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by ca...@apache.org on 2022/11/09 12:27:38 UTC

[iotdb] branch master updated: [IOTDB-4745] Add ADD_NEW_NODE state for ConfigNodeProcedure (#7743)

This is an automated email from the ASF dual-hosted git repository.

caogaofei pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/master by this push:
     new 2c5f012540 [IOTDB-4745] Add ADD_NEW_NODE state for ConfigNodeProcedure (#7743)
2c5f012540 is described below

commit 2c5f01254050f3921ceeff0c21298f90b666dd23
Author: Beyyes <cg...@foxmail.com>
AuthorDate: Wed Nov 9 20:27:30 2022 +0800

    [IOTDB-4745] Add ADD_NEW_NODE state for ConfigNodeProcedure (#7743)
---
 .../confignode/client/ConfigNodeRequestType.java   |  2 +-
 .../client/sync/SyncConfigNodeClientPool.java      |  5 +-
 .../iotdb/confignode/manager/ConsensusManager.java | 47 ++++++++++------
 .../procedure/env/ConfigNodeProcedureEnv.java      | 62 ++++++++++++----------
 .../procedure/env/DataNodeRemoveHandler.java       | 11 ++--
 .../impl/node/AddConfigNodeProcedure.java          | 40 +++++---------
 .../impl/node/RemoveDataNodeProcedure.java         |  2 +
 .../procedure/state/AddConfigNodeState.java        |  3 +-
 .../thrift/ConfigNodeRPCServiceProcessor.java      |  8 +++
 .../java/org/apache/iotdb/it/env/AbstractEnv.java  |  1 +
 .../apache/iotdb/db/client/ConfigNodeClient.java   |  5 ++
 .../java/org/apache/iotdb/rpc/TSStatusCode.java    |  1 +
 .../src/main/thrift/confignode.thrift              |  3 ++
 13 files changed, 110 insertions(+), 80 deletions(-)

diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/client/ConfigNodeRequestType.java b/confignode/src/main/java/org/apache/iotdb/confignode/client/ConfigNodeRequestType.java
index d9ee56ae25..50518cf18c 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/client/ConfigNodeRequestType.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/client/ConfigNodeRequestType.java
@@ -20,10 +20,10 @@
 package org.apache.iotdb.confignode.client;
 
 public enum ConfigNodeRequestType {
-  ADD_CONSENSUS_GROUP,
   NOTIFY_REGISTER_SUCCESS,
   REGISTER_CONFIG_NODE,
   REMOVE_CONFIG_NODE,
   DELETE_CONFIG_NODE_PEER,
+  QUERY_CONSENSUS_MANAGER_STATUS,
   STOP_CONFIG_NODE;
 }
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/client/sync/SyncConfigNodeClientPool.java b/confignode/src/main/java/org/apache/iotdb/confignode/client/sync/SyncConfigNodeClientPool.java
index 30d41a1d7b..8d156eee89 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/client/sync/SyncConfigNodeClientPool.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/client/sync/SyncConfigNodeClientPool.java
@@ -24,7 +24,6 @@ import org.apache.iotdb.common.rpc.thrift.TSStatus;
 import org.apache.iotdb.commons.client.IClientManager;
 import org.apache.iotdb.commons.client.sync.SyncConfigNodeIServiceClient;
 import org.apache.iotdb.confignode.client.ConfigNodeRequestType;
-import org.apache.iotdb.confignode.rpc.thrift.TAddConsensusGroupReq;
 import org.apache.iotdb.confignode.rpc.thrift.TConfigNodeRegisterReq;
 import org.apache.iotdb.db.client.DataNodeClientPoolFactory;
 import org.apache.iotdb.rpc.RpcUtils;
@@ -74,8 +73,6 @@ public class SyncConfigNodeClientPool {
           case REGISTER_CONFIG_NODE:
             // Only use registerConfigNode when the ConfigNode is first startup.
             return client.registerConfigNode((TConfigNodeRegisterReq) req);
-          case ADD_CONSENSUS_GROUP:
-            return client.addConsensusGroup((TAddConsensusGroupReq) req);
           case NOTIFY_REGISTER_SUCCESS:
             client.notifyRegisterSuccess();
             return null;
@@ -83,6 +80,8 @@ public class SyncConfigNodeClientPool {
             return removeConfigNode((TConfigNodeLocation) req, client);
           case DELETE_CONFIG_NODE_PEER:
             return client.deleteConfigNodePeer((TConfigNodeLocation) req);
+          case QUERY_CONSENSUS_MANAGER_STATUS:
+            return client.isConsensusInitialized();
           case STOP_CONFIG_NODE:
             // Only use stopConfigNode when the ConfigNode is removed.
             return client.stopConfigNode((TConfigNodeLocation) req);
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/manager/ConsensusManager.java b/confignode/src/main/java/org/apache/iotdb/confignode/manager/ConsensusManager.java
index fa6487b0fe..b0b8f44794 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/manager/ConsensusManager.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/manager/ConsensusManager.java
@@ -35,6 +35,7 @@ import org.apache.iotdb.confignode.manager.node.NodeManager;
 import org.apache.iotdb.consensus.ConsensusFactory;
 import org.apache.iotdb.consensus.IConsensus;
 import org.apache.iotdb.consensus.common.Peer;
+import org.apache.iotdb.consensus.common.response.ConsensusGenericResponse;
 import org.apache.iotdb.consensus.common.response.ConsensusReadResponse;
 import org.apache.iotdb.consensus.common.response.ConsensusWriteResponse;
 import org.apache.iotdb.consensus.config.ConsensusConfig;
@@ -51,6 +52,7 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
 
 /** ConsensusManager maintains consensus class, request will redirect to consensus layer */
 public class ConsensusManager {
@@ -223,24 +225,37 @@ public class ConsensusManager {
   }
 
   /**
-   * Add new ConfigNode Peer into PartitionRegion
+   * Tell the group to [create a new Peer on new node] and [add this member to join the group].
    *
-   * @param configNodeLocation The new ConfigNode
-   * @throws AddPeerException When addPeer doesn't success
+   * <p>Using this method to replace `createPeer` and `addPeer`.
+   *
+   * @param originalConfigNodes the original members of the existed group
+   * @param newConfigNode the new member
    */
-  public void addConfigNodePeer(TConfigNodeLocation configNodeLocation) throws AddPeerException {
-    boolean result =
-        consensusImpl
-            .addPeer(
-                consensusGroupId,
-                new Peer(
-                    consensusGroupId,
-                    configNodeLocation.getConfigNodeId(),
-                    configNodeLocation.getConsensusEndPoint()))
-            .isSuccess();
-
-    if (!result) {
-      throw new AddPeerException(configNodeLocation);
+  public void addNewNodeToExistedGroup(
+      List<TConfigNodeLocation> originalConfigNodes, TConfigNodeLocation newConfigNode)
+      throws AddPeerException {
+    Peer newPeer =
+        new Peer(
+            consensusGroupId,
+            newConfigNode.getConfigNodeId(),
+            newConfigNode.getConsensusEndPoint());
+
+    List<Peer> originalPeers =
+        originalConfigNodes.stream()
+            .map(
+                node ->
+                    new Peer(consensusGroupId, node.getConfigNodeId(), node.getConsensusEndPoint()))
+            .collect(Collectors.toList());
+
+    LOGGER.info("AddNewNodeToExistedGroup, newPeer: {}, originalPeers: {}", newPeer, originalPeers);
+
+    ConsensusGenericResponse response =
+        consensusImpl.addNewNodeToExistedGroup(consensusGroupId, newPeer, originalPeers);
+    if (!response.isSuccess()) {
+      LOGGER.error(
+          "Execute addNewNodeToExistedGroup for ConfigNode failed, response: {}", response);
+      throw new AddPeerException(newConfigNode);
     }
   }
 
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/procedure/env/ConfigNodeProcedureEnv.java b/confignode/src/main/java/org/apache/iotdb/confignode/procedure/env/ConfigNodeProcedureEnv.java
index 8724be24ec..97a97825d9 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/procedure/env/ConfigNodeProcedureEnv.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/procedure/env/ConfigNodeProcedureEnv.java
@@ -40,7 +40,6 @@ import org.apache.iotdb.confignode.consensus.request.write.confignode.RemoveConf
 import org.apache.iotdb.confignode.consensus.request.write.region.CreateRegionGroupsPlan;
 import org.apache.iotdb.confignode.consensus.request.write.storagegroup.DeleteStorageGroupPlan;
 import org.apache.iotdb.confignode.consensus.request.write.storagegroup.PreDeleteStorageGroupPlan;
-import org.apache.iotdb.confignode.exception.AddConsensusGroupException;
 import org.apache.iotdb.confignode.exception.AddPeerException;
 import org.apache.iotdb.confignode.exception.StorageGroupNotExistsException;
 import org.apache.iotdb.confignode.manager.ClusterSchemaManager;
@@ -56,7 +55,6 @@ import org.apache.iotdb.confignode.persistence.node.NodeInfo;
 import org.apache.iotdb.confignode.procedure.exception.ProcedureException;
 import org.apache.iotdb.confignode.procedure.scheduler.LockQueue;
 import org.apache.iotdb.confignode.procedure.scheduler.ProcedureScheduler;
-import org.apache.iotdb.confignode.rpc.thrift.TAddConsensusGroupReq;
 import org.apache.iotdb.consensus.ConsensusFactory;
 import org.apache.iotdb.mpp.rpc.thrift.TActiveTriggerInstanceReq;
 import org.apache.iotdb.mpp.rpc.thrift.TCreateDataRegionReq;
@@ -206,35 +204,45 @@ public class ConfigNodeProcedureEnv {
   }
 
   /**
-   * Let the remotely new ConfigNode build the ConsensusGroup
+   * Only ConfigNode leader will invoke this method. Add the new ConfigNode Peer into
+   * ConfigNodeRegionGroup.
    *
-   * @param tConfigNodeLocation New ConfigNode's location
+   * @param newConfigNode The new ConfigNode
+   * @throws AddPeerException When addNewNodeToExistedGroup doesn't success
    */
-  public void addConsensusGroup(TConfigNodeLocation tConfigNodeLocation)
-      throws AddConsensusGroupException {
-    List<TConfigNodeLocation> configNodeLocations =
-        new ArrayList<>(configManager.getNodeManager().getRegisteredConfigNodes());
-    configNodeLocations.add(tConfigNodeLocation);
-    TSStatus status =
-        (TSStatus)
-            SyncConfigNodeClientPool.getInstance()
-                .sendSyncRequestToConfigNodeWithRetry(
-                    tConfigNodeLocation.getInternalEndPoint(),
-                    new TAddConsensusGroupReq(configNodeLocations),
-                    ConfigNodeRequestType.ADD_CONSENSUS_GROUP);
-    if (status.getCode() != TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
-      throw new AddConsensusGroupException(tConfigNodeLocation);
+  public void addNewNodeToExistedGroup(TConfigNodeLocation newConfigNode) throws AddPeerException {
+    for (int i = 0; i < 3; i++) {
+      try {
+        // sleep 5 seconds to wait the registered ConfigNode completed initConsensusManager
+        TimeUnit.SECONDS.sleep(5);
+      } catch (InterruptedException e) {
+        Thread.currentThread().interrupt();
+        LOG.warn("Unexpected interruption in ConfigNode addNewNodeToExistedGroup", e);
+      }
+
+      TSStatus status =
+          (TSStatus)
+              SyncConfigNodeClientPool.getInstance()
+                  .sendSyncRequestToConfigNodeWithRetry(
+                      newConfigNode.getInternalEndPoint(),
+                      null,
+                      ConfigNodeRequestType.QUERY_CONSENSUS_MANAGER_STATUS);
+      if (status.getCode() == TSStatusCode.SUCCESS_STATUS.getStatusCode()) {
+        break;
+      }
+
+      LOG.info(
+          "The ConsensusManager of Registered-ConfigNode is not initialized, wait 7 seconds, ConfigNode: {}, status: {}",
+          newConfigNode,
+          status);
     }
-  }
 
-  /**
-   * Leader will add the new ConfigNode Peer into PartitionRegion
-   *
-   * @param configNodeLocation The new ConfigNode
-   * @throws AddPeerException When addPeer doesn't success
-   */
-  public void addConfigNodePeer(TConfigNodeLocation configNodeLocation) throws AddPeerException {
-    configManager.getConsensusManager().addConfigNodePeer(configNodeLocation);
+    List<TConfigNodeLocation> originalConfigNodes =
+        new ArrayList<>(configManager.getNodeManager().getRegisteredConfigNodes());
+
+    configManager
+        .getConsensusManager()
+        .addNewNodeToExistedGroup(originalConfigNodes, newConfigNode);
   }
 
   /**
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/procedure/env/DataNodeRemoveHandler.java b/confignode/src/main/java/org/apache/iotdb/confignode/procedure/env/DataNodeRemoveHandler.java
index 2e29166188..beabdbbdf8 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/procedure/env/DataNodeRemoveHandler.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/procedure/env/DataNodeRemoveHandler.java
@@ -412,14 +412,18 @@ public class DataNodeRemoveHandler {
    * @param dataNode old data node
    */
   public void stopDataNode(TDataNodeLocation dataNode) {
-    LOGGER.info("{}, Begin to stop DataNode {}", REMOVE_DATANODE_PROCESS, dataNode);
+
     AsyncDataNodeClientPool.getInstance().resetClient(dataNode.getInternalEndPoint());
     TSStatus status =
         SyncDataNodeClientPool.getInstance()
             .sendSyncRequestToDataNodeWithRetry(
                 dataNode.getInternalEndPoint(), dataNode, DataNodeRequestType.STOP_DATA_NODE);
     configManager.getNodeManager().removeNodeCache(dataNode.getDataNodeId());
-    LOGGER.info("{}, Stop Data Node {} result: {}", REMOVE_DATANODE_PROCESS, dataNode, status);
+    LOGGER.info(
+        "{}, Stop DataNode execute finished, DataNode: {}, result: {}",
+        REMOVE_DATANODE_PROCESS,
+        dataNode,
+        status);
   }
 
   /**
@@ -536,8 +540,7 @@ public class DataNodeRemoveHandler {
    * @param tDataNodeLocation data node location
    */
   public void removeDataNodePersistence(TDataNodeLocation tDataNodeLocation) {
-    List<TDataNodeLocation> removeDataNodes = new ArrayList<>();
-    removeDataNodes.add(tDataNodeLocation);
+    List<TDataNodeLocation> removeDataNodes = Collections.singletonList(tDataNodeLocation);
     configManager.getConsensusManager().write(new RemoveDataNodePlan(removeDataNodes));
   }
 
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/node/AddConfigNodeProcedure.java b/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/node/AddConfigNodeProcedure.java
index 338254c8f8..c0a7982774 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/node/AddConfigNodeProcedure.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/node/AddConfigNodeProcedure.java
@@ -58,19 +58,13 @@ public class AddConfigNodeProcedure extends AbstractNodeProcedure<AddConfigNodeS
     try {
       switch (state) {
         case ADD_CONFIG_NODE_PREPARE:
-          setNextState(AddConfigNodeState.CREATE_PEER);
+          setNextState(AddConfigNodeState.ADD_NEW_NODE);
           break;
-        case CREATE_PEER:
-          LOG.info("Executing createPeerForConsensusGroup on {}...", tConfigNodeLocation);
-          env.addConsensusGroup(tConfigNodeLocation);
-          setNextState(AddConfigNodeState.ADD_PEER);
-          LOG.info("Successfully createPeerForConsensusGroup on {}", tConfigNodeLocation);
-          break;
-        case ADD_PEER:
-          LOG.info("Executing addPeer {}...", tConfigNodeLocation);
-          env.addConfigNodePeer(tConfigNodeLocation);
+        case ADD_NEW_NODE:
+          LOG.info("Executing addNewNodeToExistedGroup {}...", tConfigNodeLocation);
+          env.addNewNodeToExistedGroup(tConfigNodeLocation);
           setNextState(AddConfigNodeState.REGISTER_SUCCESS);
-          LOG.info("Successfully addPeer {}", tConfigNodeLocation);
+          LOG.info("Successfully addNewNodeToExistedGroup {}", tConfigNodeLocation);
           break;
         case REGISTER_SUCCESS:
           env.notifyRegisterSuccess(tConfigNodeLocation);
@@ -81,7 +75,7 @@ public class AddConfigNodeProcedure extends AbstractNodeProcedure<AddConfigNodeS
       }
     } catch (Exception e) {
       if (isRollbackSupported(state)) {
-        setFailure(new ProcedureException("Add Config Node failed " + state));
+        setFailure(new ProcedureException("Add ConfigNode failed " + state));
       } else {
         LOG.error(
             "Retrievable error trying to add config node {}, state {}",
@@ -99,26 +93,18 @@ public class AddConfigNodeProcedure extends AbstractNodeProcedure<AddConfigNodeS
   @Override
   protected void rollbackState(ConfigNodeProcedureEnv env, AddConfigNodeState state)
       throws ProcedureException {
-    switch (state) {
-      case CREATE_PEER:
-        env.deleteConfigNodePeer(tConfigNodeLocation);
-        LOG.info("Rollback add consensus group:{}", tConfigNodeLocation);
-        break;
-      case ADD_PEER:
-        env.removeConfigNodePeer(tConfigNodeLocation);
-        LOG.info("Rollback remove peer:{}", tConfigNodeLocation);
-        break;
+    if (state == AddConfigNodeState.ADD_NEW_NODE) {
+      LOG.info("Rollback in AddConfigNodeProcedure, execute RemovePeer: {}", tConfigNodeLocation);
+      env.removeConfigNodePeer(tConfigNodeLocation);
+
+      LOG.info("Rollback in AddConfigNodeProcedure, execute DeletePeer: {}", tConfigNodeLocation);
+      env.deleteConfigNodePeer(tConfigNodeLocation);
     }
   }
 
   @Override
   protected boolean isRollbackSupported(AddConfigNodeState state) {
-    switch (state) {
-      case CREATE_PEER:
-      case ADD_PEER:
-        return true;
-    }
-    return false;
+    return state == AddConfigNodeState.ADD_NEW_NODE;
   }
 
   @Override
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/node/RemoveDataNodeProcedure.java b/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/node/RemoveDataNodeProcedure.java
index 6b7272c36f..3380aa3c18 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/node/RemoveDataNodeProcedure.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/node/RemoveDataNodeProcedure.java
@@ -96,6 +96,8 @@ public class RemoveDataNodeProcedure extends AbstractNodeProcedure<RemoveDataNod
           break;
         case STOP_DATA_NODE:
           // TODO if region migrate is failed, don't execute STOP_DATA_NODE
+          LOG.info(
+              "{}, Begin to stop DataNode: {}", REMOVE_DATANODE_PROCESS, disableDataNodeLocation);
           env.getDataNodeRemoveHandler().removeDataNodePersistence(disableDataNodeLocation);
           env.getDataNodeRemoveHandler().stopDataNode(disableDataNodeLocation);
           return Flow.NO_MORE_STATE;
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/procedure/state/AddConfigNodeState.java b/confignode/src/main/java/org/apache/iotdb/confignode/procedure/state/AddConfigNodeState.java
index a7f1912609..31c94e300b 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/procedure/state/AddConfigNodeState.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/procedure/state/AddConfigNodeState.java
@@ -21,7 +21,6 @@ package org.apache.iotdb.confignode.procedure.state;
 
 public enum AddConfigNodeState {
   ADD_CONFIG_NODE_PREPARE,
-  CREATE_PEER,
-  ADD_PEER,
+  ADD_NEW_NODE,
   REGISTER_SUCCESS
 }
diff --git a/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessor.java b/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessor.java
index 383d413e31..1ead8f76cf 100644
--- a/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessor.java
+++ b/confignode/src/main/java/org/apache/iotdb/confignode/service/thrift/ConfigNodeRPCServiceProcessor.java
@@ -454,6 +454,14 @@ public class ConfigNodeRPCServiceProcessor implements IConfigNodeRPCService.Ifac
     return StatusUtils.OK;
   }
 
+  @Override
+  public TSStatus isConsensusInitialized() throws TException {
+    if (configManager.getConsensusManager() != null) {
+      return new TSStatus(TSStatusCode.SUCCESS_STATUS.getStatusCode());
+    }
+    return new TSStatus(TSStatusCode.CONSENSUS_NOT_INITIALIZED.getStatusCode());
+  }
+
   /** For leader to remove ConfigNode configuration in consensus layer */
   @Override
   public TSStatus removeConfigNode(TConfigNodeLocation configNodeLocation) throws TException {
diff --git a/integration-test/src/main/java/org/apache/iotdb/it/env/AbstractEnv.java b/integration-test/src/main/java/org/apache/iotdb/it/env/AbstractEnv.java
index 8f28163346..7603c8552c 100644
--- a/integration-test/src/main/java/org/apache/iotdb/it/env/AbstractEnv.java
+++ b/integration-test/src/main/java/org/apache/iotdb/it/env/AbstractEnv.java
@@ -201,6 +201,7 @@ public abstract class AbstractEnv implements BaseEnv {
       }
       logger.info("Start cluster costs: {}s", (System.currentTimeMillis() - startTime) / 1000.0);
     } catch (Exception e) {
+      logger.error("exception in testWorking of ClusterID, message: {}", e.getMessage(), e);
       fail("After 30 times retry, the cluster can't work!");
     }
   }
diff --git a/server/src/main/java/org/apache/iotdb/db/client/ConfigNodeClient.java b/server/src/main/java/org/apache/iotdb/db/client/ConfigNodeClient.java
index 45db274090..cf67cba8e5 100644
--- a/server/src/main/java/org/apache/iotdb/db/client/ConfigNodeClient.java
+++ b/server/src/main/java/org/apache/iotdb/db/client/ConfigNodeClient.java
@@ -814,6 +814,11 @@ public class ConfigNodeClient
     throw new TException("DataNode to ConfigNode client doesn't support notifyRegisterSuccess.");
   }
 
+  @Override
+  public TSStatus isConsensusInitialized() throws TException {
+    throw new TException("DataNode to ConfigNode client doesn't support isConsensusInitialized.");
+  }
+
   @Override
   public TSStatus removeConfigNode(TConfigNodeLocation configNodeLocation) throws TException {
     throw new TException("DataNode to ConfigNode client doesn't support removeConfigNode.");
diff --git a/service-rpc/src/main/java/org/apache/iotdb/rpc/TSStatusCode.java b/service-rpc/src/main/java/org/apache/iotdb/rpc/TSStatusCode.java
index 134f3a7bce..a76e4c2922 100644
--- a/service-rpc/src/main/java/org/apache/iotdb/rpc/TSStatusCode.java
+++ b/service-rpc/src/main/java/org/apache/iotdb/rpc/TSStatusCode.java
@@ -149,6 +149,7 @@ public enum TSStatusCode {
   DELETE_REGION_ERROR(712),
   CACHE_UPDATE_FAIL(713),
   NODE_DESERIALIZE_ERROR(714),
+  CONSENSUS_NOT_INITIALIZED(715),
 
   // configuration
   CONFIG_ERROR(800),
diff --git a/thrift-confignode/src/main/thrift/confignode.thrift b/thrift-confignode/src/main/thrift/confignode.thrift
index 40535b771b..427f156ed5 100644
--- a/thrift-confignode/src/main/thrift/confignode.thrift
+++ b/thrift-confignode/src/main/thrift/confignode.thrift
@@ -809,6 +809,9 @@ service IConfigNodeRPCService {
   /** The ConfigNode-leader will notify the Non-Seed-ConfigNode that the registration success */
   common.TSStatus notifyRegisterSuccess()
 
+  /** The ConfigNode-leader using this method to query that if the Non-Seed-ConfigNode has initialized the ConsensusManager */
+  common.TSStatus isConsensusInitialized()
+
   /**
    * Remove the specific ConfigNode from the cluster
    *