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

jt2594838 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 3eddf083968 Fix pipe write reject retry handling (#18098)
3eddf083968 is described below

commit 3eddf0839686b0677ef028c572ffcc6f6adeb3c1
Author: Caideyipi <[email protected]>
AuthorDate: Fri Jul 3 12:33:33 2026 +0800

    Fix pipe write reject retry handling (#18098)
---
 .../dataregion/DataRegionStateMachine.java         |  3 +-
 .../dataregion/DataRegionStateMachineTest.java     | 93 ++++++++++++++++++++++
 2 files changed, 95 insertions(+), 1 deletion(-)

diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/consensus/statemachine/dataregion/DataRegionStateMachine.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/consensus/statemachine/dataregion/DataRegionStateMachine.java
index b99304055a9..bf31a16dfd8 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/consensus/statemachine/dataregion/DataRegionStateMachine.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/consensus/statemachine/dataregion/DataRegionStateMachine.java
@@ -248,7 +248,8 @@ public class DataRegionStateMachine extends 
BaseStateMachine {
     int retryTime = 0;
     while (retryTime < MAX_WRITE_RETRY_TIMES) {
       result = planNode.accept(new DataExecutionVisitor(), region);
-      if (needRetry(result.getCode())) {
+      // Let pipe retry with the original event instead of retrying a possibly 
mutated node here.
+      if (needRetry(result.getCode()) && !planNode.isGeneratedByPipe()) {
         retryTime++;
         logger.debug(
             "write operation failed because {}, retryTime: {}.", 
result.getCode(), retryTime);
diff --git 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/consensus/statemachine/dataregion/DataRegionStateMachineTest.java
 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/consensus/statemachine/dataregion/DataRegionStateMachineTest.java
index c2ccb56fa72..c6ab83d7b6f 100644
--- 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/consensus/statemachine/dataregion/DataRegionStateMachineTest.java
+++ 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/consensus/statemachine/dataregion/DataRegionStateMachineTest.java
@@ -19,18 +19,26 @@
 
 package org.apache.iotdb.db.consensus.statemachine.dataregion;
 
+import org.apache.iotdb.common.rpc.thrift.TSStatus;
 import org.apache.iotdb.commons.exception.IllegalPathException;
 import org.apache.iotdb.commons.path.PartialPath;
+import 
org.apache.iotdb.commons.queryengine.plan.planner.plan.node.IPlanVisitor;
+import org.apache.iotdb.commons.queryengine.plan.planner.plan.node.PlanNode;
 import org.apache.iotdb.commons.queryengine.plan.planner.plan.node.PlanNodeId;
 import org.apache.iotdb.db.queryengine.plan.planner.plan.node.write.InsertNode;
 import 
org.apache.iotdb.db.queryengine.plan.planner.plan.node.write.InsertRowNode;
 import 
org.apache.iotdb.db.queryengine.plan.planner.plan.node.write.InsertRowsNode;
+import org.apache.iotdb.rpc.TSStatusCode;
 
 import org.apache.tsfile.enums.TSDataType;
 import org.junit.Assert;
 import org.junit.Test;
 
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
 public class DataRegionStateMachineTest {
@@ -119,4 +127,89 @@ public class DataRegionStateMachineTest {
     InsertNode mergedNode = list.get(0).mergeInsertNode(list);
     Assert.assertTrue(mergedNode instanceof InsertRowsNode);
   }
+
+  @Test
+  public void testPipeGeneratedWriteProcessRejectSkipsStateMachineRetry() {
+    final DataRegionStateMachine stateMachine = new 
DataRegionStateMachine(null);
+    final RetryControlledPlanNode planNode = new RetryControlledPlanNode(true);
+
+    final TSStatus status = stateMachine.write(planNode);
+
+    Assert.assertEquals(TSStatusCode.WRITE_PROCESS_REJECT.getStatusCode(), 
status.getCode());
+    Assert.assertEquals(1, planNode.getAcceptCount());
+  }
+
+  @Test
+  public void testNonPipeWriteProcessRejectCanStillRetry() {
+    final DataRegionStateMachine stateMachine = new 
DataRegionStateMachine(null);
+    final RetryControlledPlanNode planNode = new 
RetryControlledPlanNode(false);
+
+    final TSStatus status = stateMachine.write(planNode);
+
+    Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), 
status.getCode());
+    Assert.assertEquals(2, planNode.getAcceptCount());
+  }
+
+  private static class RetryControlledPlanNode extends PlanNode {
+
+    private final boolean markAsPipeOnFirstAccept;
+    private int acceptCount = 0;
+
+    private RetryControlledPlanNode(final boolean markAsPipeOnFirstAccept) {
+      super(new PlanNodeId("test"));
+      this.markAsPipeOnFirstAccept = markAsPipeOnFirstAccept;
+    }
+
+    private int getAcceptCount() {
+      return acceptCount;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <R, C> R accept(final IPlanVisitor<R, C> visitor, final C context) {
+      ++acceptCount;
+      if (markAsPipeOnFirstAccept) {
+        markAsGeneratedByPipe();
+      }
+      return (R)
+          new TSStatus(
+              (acceptCount == 1 ? TSStatusCode.WRITE_PROCESS_REJECT : 
TSStatusCode.SUCCESS_STATUS)
+                  .getStatusCode());
+    }
+
+    @Override
+    public List<PlanNode> getChildren() {
+      return Collections.emptyList();
+    }
+
+    @Override
+    public void addChild(final PlanNode child) {
+      // No children.
+    }
+
+    @Override
+    public PlanNode clone() {
+      return new RetryControlledPlanNode(markAsPipeOnFirstAccept);
+    }
+
+    @Override
+    public int allowedChildCount() {
+      return NO_CHILD_ALLOWED;
+    }
+
+    @Override
+    public List<String> getOutputColumnNames() {
+      return Collections.emptyList();
+    }
+
+    @Override
+    protected void serializeAttributes(final ByteBuffer byteBuffer) {
+      // This test node is never serialized.
+    }
+
+    @Override
+    protected void serializeAttributes(final DataOutputStream stream) throws 
IOException {
+      // This test node is never serialized.
+    }
+  }
 }

Reply via email to