This is an automated email from the ASF dual-hosted git repository.
jt2594838 pushed a commit to branch dev/1.3
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/dev/1.3 by this push:
new 7790a6f657f Preserve write-path causes and return delete failure
details (#18933) (#18993)
7790a6f657f is described below
commit 7790a6f657fd8d70fbd14e5e569ddaf4a9f52f33
Author: Caideyipi <[email protected]>
AuthorDate: Fri Oct 23 14:11:53 2026 +0800
Preserve write-path causes and return delete failure details (#18933)
(#18993)
* Preserve causes in write-path diagnostics
* Return delete failure details to clients
* Avoid stack traces for expected write-path errors
---
.../dataregion/DataExecutionVisitor.java | 7 ++-
.../timeindex/FileTimeIndexCacheRecorder.java | 6 +--
.../dataregion/wal/buffer/WALBuffer.java | 3 +-
.../dataregion/wal/recover/WALNodeRecoverTask.java | 3 +-
.../dataregion/DataExecutionVisitorTest.java | 62 ++++++++++++++++++++++
5 files changed, 74 insertions(+), 7 deletions(-)
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/consensus/statemachine/dataregion/DataExecutionVisitor.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/consensus/statemachine/dataregion/DataExecutionVisitor.java
index fd78fec2d43..b519cf07d83 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/consensus/statemachine/dataregion/DataExecutionVisitor.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/consensus/statemachine/dataregion/DataExecutionVisitor.java
@@ -243,9 +243,12 @@ public class DataExecutionVisitor extends
PlanVisitor<TSStatus, DataRegion> {
return StatusUtils.OK;
} catch (WriteProcessRejectException e) {
return RpcUtils.getStatus(e.getErrorCode(), e.getMessage());
- } catch (IOException | IllegalPathException e) {
+ } catch (IOException e) {
LOGGER.error("Error in executing plan node: {}", node, e);
- return new TSStatus(TSStatusCode.WRITE_PROCESS_ERROR.getStatusCode());
+ return RpcUtils.getStatus(TSStatusCode.WRITE_PROCESS_ERROR,
e.getMessage());
+ } catch (IllegalPathException e) {
+ LOGGER.error("{}: {}", node, e.getMessage());
+ return RpcUtils.getStatus(TSStatusCode.WRITE_PROCESS_ERROR,
e.getMessage());
} finally {
dataRegion.writeUnlock();
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/tsfile/timeindex/FileTimeIndexCacheRecorder.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/tsfile/timeindex/FileTimeIndexCacheRecorder.java
index 75fd5fb50f3..fa85af70ce6 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/tsfile/timeindex/FileTimeIndexCacheRecorder.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/tsfile/timeindex/FileTimeIndexCacheRecorder.java
@@ -102,7 +102,7 @@ public class FileTimeIndexCacheRecorder {
buffer.flip();
writer.write(buffer);
} catch (IOException e) {
- LOGGER.warn("Meet error when record FileTimeIndexCache: {}",
e.getMessage());
+ LOGGER.warn("Meet error when record FileTimeIndexCache: {}",
e.getMessage(), e);
}
});
if (!result) {
@@ -155,7 +155,7 @@ public class FileTimeIndexCacheRecorder {
}
}
} catch (IOException e) {
- LOGGER.warn("Meet error when compact FileTimeIndexCache:
{}", e.getMessage());
+ LOGGER.warn("Meet error when compact FileTimeIndexCache:
{}", e.getMessage(), e);
}
});
if (!result) {
@@ -199,7 +199,7 @@ public class FileTimeIndexCacheRecorder {
writer.close();
deleteFileOrDirectory(writer.getLogFile(), true);
} catch (IOException e) {
- LOGGER.warn("Meet error when close FileTimeIndexCache: {}",
e.getMessage());
+ LOGGER.warn("Meet error when close FileTimeIndexCache: {}",
e.getMessage(), e);
}
}
}
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/wal/buffer/WALBuffer.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/wal/buffer/WALBuffer.java
index 08d1ad384bb..7a42a160ec2 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/wal/buffer/WALBuffer.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/wal/buffer/WALBuffer.java
@@ -765,7 +765,8 @@ public class WALBuffer extends AbstractWALBuffer {
"Fail to read memTable ids from the wal file {} of wal node
{}: {}",
id,
identifier,
- e.getMessage());
+ e.getMessage(),
+ e);
} catch (IOException e) {
logger.warn(
"Fail to read memTable ids from the wal file {} of wal node
{}.",
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/wal/recover/WALNodeRecoverTask.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/wal/recover/WALNodeRecoverTask.java
index 18bb293792a..b2ee8a9436d 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/wal/recover/WALNodeRecoverTask.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/storageengine/dataregion/wal/recover/WALNodeRecoverTask.java
@@ -292,7 +292,8 @@ public class WALNodeRecoverTask implements Runnable {
logger.warn(
"Fail to read memTable ids from the wal file {} of wal node: {}",
walFile.getAbsoluteFile(),
- e.getMessage());
+ logDirectory.getName(),
+ e);
} catch (IOException e) {
logger.warn(
"Fail to read memTable ids from the wal file {} of wal node.",
diff --git
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/consensus/statemachine/dataregion/DataExecutionVisitorTest.java
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/consensus/statemachine/dataregion/DataExecutionVisitorTest.java
new file mode 100644
index 00000000000..7f72fd6a231
--- /dev/null
+++
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/consensus/statemachine/dataregion/DataExecutionVisitorTest.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.iotdb.db.consensus.statemachine.dataregion;
+
+import org.apache.iotdb.common.rpc.thrift.TSStatus;
+import org.apache.iotdb.commons.path.PartialPath;
+import org.apache.iotdb.db.queryengine.plan.planner.plan.node.PlanNodeId;
+import
org.apache.iotdb.db.queryengine.plan.planner.plan.node.write.DeleteDataNode;
+import org.apache.iotdb.db.storageengine.dataregion.DataRegion;
+import org.apache.iotdb.rpc.TSStatusCode;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import java.io.IOException;
+import java.util.Collections;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyLong;
+
+public class DataExecutionVisitorTest {
+
+ @Test
+ public void testDeleteFailureReturnsMessage() throws Exception {
+ final DataRegion dataRegion = Mockito.mock(DataRegion.class);
+ Mockito.when(dataRegion.getDatabaseName()).thenReturn("root.sg");
+ final IOException failure = new IOException("injected delete failure");
+ Mockito.doThrow(failure)
+ .when(dataRegion)
+ .deleteByDevice(any(PartialPath.class), anyLong(), anyLong(),
anyLong());
+
+ final DeleteDataNode node =
+ new DeleteDataNode(
+ new PlanNodeId("delete-error-test"),
+ Collections.singletonList(new PartialPath("root.sg.device.s1")),
+ Long.MIN_VALUE,
+ Long.MAX_VALUE);
+
+ final TSStatus status = new DataExecutionVisitor().visitDeleteData(node,
dataRegion);
+
+ Assert.assertEquals(TSStatusCode.WRITE_PROCESS_ERROR.getStatusCode(),
status.getCode());
+ Assert.assertEquals(failure.getMessage(), status.getMessage());
+ Mockito.verify(dataRegion).writeUnlock();
+ }
+}