You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 9047875
Browse filesBrowse the repository at this point in the historyBrowse files
Fix MIGRATE REGION falsely reported complete on ConfigNode leader switch
When the ConfigNode leader is gracefully stopped (or loses leadership)
while AddRegionPeerProcedure is waiting for the coordinator DataNode's
AddRegionPeer task to finish, RegionMaintainHandler.waitTaskFinish()
is interrupted and returns PROCESSING. The DO_ADD_REGION_PEER state
previously treated PROCESSING as a no-op terminal state
(return Flow.NO_MORE_STATE), silently ending the AddRegionPeerProcedure
without success or rollback.
The parent RegionMigrateProcedure had already persisted at
CHECK_ADD_REGION_PEER, so the new leader resumed there directly. Its
isDataNodeContainsRegion() check only inspects the partition table's
location list, which is written at CREATE_NEW_REGION_PEER (long before
the snapshot finishes transferring). It therefore passed, the source
replica was removed, and the migration was declared a success while the
destination replica was still in Adding state and had not received the
snapshot. Queries against the region returned incorrect results during
the gap (observed: ~17 min until the destination became active).
Fix: in the PROCESSING branch, stay at DO_ADD_REGION_PEER and persist
it (HAS_MORE_STATE) instead of ending. After recovery the new leader
re-enters DO_ADD_REGION_PEER and re-polls the coordinator task until it
truly reaches SUCCESS or FAIL. The re-poll is idempotent: the
isStateDeserialized() guard skips re-submitting after a restart, and the
coordinator DataNode dedups by taskId (putIfAbsent) even on a same-process
re-execute, so the AddRegionPeer task is never submitted twice. If the
coordinator crashed and lost its task table, the poll returns
TASK_NOT_EXIST and falls through to the existing FAIL/rollback path.
Add cnLeaderSwitchDuringDoAddPeerTest for each consensus protocol
(IoTConsensus, IoTConsensusV2 batch/stream, Ratis). Existing daily
ConfigNode-crash ITs all use stopForcibly() (SIGKILL), which kills the
process before it can run the PROCESSING branch; the new test uses a
graceful stop() (SIGTERM) of the leader among 3 ConfigNodes so the
interrupted PROCESSING path is actually exercised across a real leader
switch.
Copy file name to clipboardExpand all lines: integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/IoTDBRegionOperationReliabilityITFramework.java
+43Lines changed: 43 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -119,6 +119,27 @@ public class IoTDBRegionOperationReliabilityITFramework {
119
119
LOGGER.info("Cluster has been restarted");
120
120
};
121
121
122
+
/**
123
+
* Gracefully stop (SIGTERM, not a forcible kill) the ConfigNode that hit the kill point, then
124
+
* restart it. A graceful stop lets the ConfigNode run its shutdown hooks, which interrupts the
125
+
* in-flight region-operation procedure worker. This reproduces a leader switch / graceful
126
+
* shutdown during AddRegionPeer: the interrupted {@code waitTaskFinish()} returns PROCESSING
127
+
* while the AddRegionPeerTask is still running on the coordinator DataNode. The procedure must
128
+
* NOT silently end here, otherwise the parent RegionMigrateProcedure would falsely treat AddPeer
129
+
* as complete and remove the source replica before the destination replica is actually Running.
130
+
* See AddRegionPeerProcedure#executeFromState DO_ADD_REGION_PEER PROCESSING branch.
Copy file name to clipboardExpand all lines: integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/daily/iotv1/IoTDBRegionMigrateConfigNodeCrashIoTV1IT.java
Copy file name to clipboardExpand all lines: integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/daily/iotv2/batch/IoTDBRegionMigrateConfigNodeCrashIoTV2BatchIT.java
Copy file name to clipboardExpand all lines: integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/daily/iotv2/stream/IoTDBRegionMigrateConfigNodeCrashIoTV2StreamIT.java
Copy file name to clipboardExpand all lines: integration-test/src/test/java/org/apache/iotdb/confignode/it/regionmigration/pass/daily/ratis/IoTDBRegionMigrateConfigNodeCrashForRatisIT.java
"waitTaskFinish() returns PROCESSING, which means the waiting has been interrupted, this procedure will end without rollback";
1004
+
"waitTaskFinish() returns PROCESSING, which means the waiting has been interrupted (ConfigNode shutdown or leader change); the AddRegionPeer task is still running on the coordinator, this procedure will stay at DO_ADD_REGION_PEER and resume polling after recovery";
1005
1005
1006
1006
publicstaticfinalStringFAILED_TO_CREATE_DATABASE_THE_TTL_SHOULD_BE_NON_NEGATIVE = "Failed to create database. The TTL should be non-negative.";
1007
1007
publicstaticfinalStringFAILED_TO_CREATE_DATABASE_THE_DATAREGIONGROUPNUM_SHOULD_BE_POSITIVE = "Failed to create database. The dataRegionGroupNum should be positive.";
Copy file name to clipboardExpand all lines: iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/region/AddRegionPeerProcedure.java
+13-1Lines changed: 13 additions & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -124,10 +124,22 @@ protected Flow executeFromState(ConfigNodeProcedureEnv env, AddRegionPeerState s
124
124
returnwarnAndRollBackAndNoMoreState(
125
125
env, handler, String.format("%s result is %s", state, result.getTaskStatus()));
126
126
casePROCESSING:
127
+
// waitTaskFinish() only returns PROCESSING when its polling loop was interrupted by
128
+
// an InterruptedException, i.e. this ConfigNode is shutting down / losing leadership
129
+
// (a user CANCEL or a coordinator disconnection both go through the FAIL branch
130
+
// above). The AddRegionPeerTask is still running on the coordinator DataNode, so we
131
+
// must NOT silently end here: doing so would let the parent RegionMigrateProcedure
132
+
// proceed to CHECK_ADD_REGION_PEER / REMOVE_REGION_PEER and remove the source replica
133
+
// before the destination replica has actually finished receiving the snapshot.
134
+
// Instead, stay in DO_ADD_REGION_PEER and persist it; after recovery the new leader
135
+
// re-enters this state and re-polls the still-running coordinator task (the
136
+
// isStateDeserialized() guard above prevents re-submitting the task) until it really
0 commit comments