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

CRZbulabula 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 38b8969258a Restore DataNode removal cleanup after child procedure 
failures (#18947)
38b8969258a is described below

commit 38b8969258adf11fd68c9394f2ce6a21d1d2e137
Author: d-wang-commit <[email protected]>
AuthorDate: Tue Oct 20 23:35:19 2026 +0800

    Restore DataNode removal cleanup after child procedure failures (#18947)
    
    Allow STOP_DATA_NODE rollback cleanup under the commit-point guard.
    Preserve execution retries and verify transient cleanup failures stay 
retryable.
---
 .../impl/node/RemoveDataNodesProcedure.java        | 25 +++++++++++-----------
 .../impl/node/RemoveDataNodePersistenceTest.java   |  2 ++
 2 files changed, 14 insertions(+), 13 deletions(-)

diff --git 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/node/RemoveDataNodesProcedure.java
 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/node/RemoveDataNodesProcedure.java
index 06986a72458..212bc1dca88 100644
--- 
a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/node/RemoveDataNodesProcedure.java
+++ 
b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/procedure/impl/node/RemoveDataNodesProcedure.java
@@ -158,19 +158,16 @@ public class RemoveDataNodesProcedure extends 
AbstractNodeProcedure<RemoveDataNo
           return Flow.NO_MORE_STATE;
       }
     } catch (Exception e) {
-      if (isRollbackSupported(state)) {
-        setFailure(new 
ProcedureException(ProcedureMessages.REMOVE_DATA_NODE_FAILED + state));
+      // Rollback support permits failure cleanup; transient execution errors 
still retry here.
+      LOG.error(
+          
ProcedureMessages.LOG_RETRIEVABLE_ERROR_TRYING_REMOVE_DATA_NODE_ARG_STATE_ARG_4EFEB850,
+          removedDataNodes,
+          state,
+          e);
+      if (getCycles() > RETRY_THRESHOLD) {
+        setFailure(new ProcedureException(ProcedureMessages.STATE_STUCK_AT + 
state));
       } else {
-        LOG.error(
-            
ProcedureMessages.LOG_RETRIEVABLE_ERROR_TRYING_REMOVE_DATA_NODE_ARG_STATE_ARG_4EFEB850,
-            removedDataNodes,
-            state,
-            e);
-        if (getCycles() > RETRY_THRESHOLD) {
-          setFailure(new ProcedureException(ProcedureMessages.STATE_STUCK_AT + 
state));
-        } else {
-          setNextState(state);
-        }
+        setNextState(state);
       }
     }
     return Flow.HAS_MORE_STATE;
@@ -291,7 +288,9 @@ public class RemoveDataNodesProcedure extends 
AbstractNodeProcedure<RemoveDataNo
 
   @Override
   protected boolean isRollbackSupported(RemoveDataNodeState state) {
-    return false;
+    // A failed migration child must still trigger node cleanup. This restores 
node statuses and
+    // stops drained nodes without undoing completed region migrations.
+    return state == RemoveDataNodeState.STOP_DATA_NODE;
   }
 
   /**
diff --git 
a/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/procedure/impl/node/RemoveDataNodePersistenceTest.java
 
b/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/procedure/impl/node/RemoveDataNodePersistenceTest.java
index 6ec10161917..e3ff2989284 100644
--- 
a/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/procedure/impl/node/RemoveDataNodePersistenceTest.java
+++ 
b/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/procedure/impl/node/RemoveDataNodePersistenceTest.java
@@ -420,12 +420,14 @@ public class RemoveDataNodePersistenceTest {
     failStatusWrite = true;
     TestProcedure procedure = procedure(NodeStatus.Running, 
RemoveDataNodeState.STOP_DATA_NODE);
     procedure.step(env);
+    assertFalse("A transient cleanup failure must remain retryable", 
procedure.isFailed());
     assertEquals(
         "The state-machine executor must retain the failed compensation step",
         RemoveDataNodeState.STOP_DATA_NODE,
         procedure.state());
     failStatusWrite = false;
     procedure.step(env);
+    assertFalse("Successful cleanup retry must not leave a failure", 
procedure.isFailed());
     assertStates(FIRST, NodeStatus.Running, NodeStatus.Running, null);
   }
 

Reply via email to