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 5b0894730cb Pipe: Respect history enable with source time range 
(#18362) (#18385)
5b0894730cb is described below

commit 5b0894730cb09a9a2b5b912ebc03ddf35373e8b2
Author: Caideyipi <[email protected]>
AuthorDate: Tue Aug 4 12:18:04 2026 +0800

    Pipe: Respect history enable with source time range (#18362) (#18385)
---
 .../pipe/it/autocreate/IoTDBPipeSourceIT.java      | 60 ++++++++++++++++++++++
 .../source/dataregion/IoTDBDataRegionSource.java   |  8 +--
 .../PipeHistoricalDataRegionTsFileSource.java      | 27 +++++-----
 .../PipeHistoricalDataRegionTsFileSourceTest.java  | 49 ++++++++++++++++++
 4 files changed, 123 insertions(+), 21 deletions(-)

diff --git 
a/integration-test/src/test/java/org/apache/iotdb/pipe/it/autocreate/IoTDBPipeSourceIT.java
 
b/integration-test/src/test/java/org/apache/iotdb/pipe/it/autocreate/IoTDBPipeSourceIT.java
index c592aca4e6a..b0428ce674d 100644
--- 
a/integration-test/src/test/java/org/apache/iotdb/pipe/it/autocreate/IoTDBPipeSourceIT.java
+++ 
b/integration-test/src/test/java/org/apache/iotdb/pipe/it/autocreate/IoTDBPipeSourceIT.java
@@ -875,6 +875,66 @@ public class IoTDBPipeSourceIT extends 
AbstractPipeDualAutoIT {
     }
   }
 
+  @Test
+  public void testSourceTimeRangeRespectsHistoryDisable() throws Exception {
+    final DataNodeWrapper receiverDataNode = receiverEnv.getDataNodeWrapper(0);
+
+    final String receiverIp = receiverDataNode.getIp();
+    final int receiverPort = receiverDataNode.getPort();
+
+    TestUtils.executeNonQueries(
+        senderEnv,
+        Arrays.asList(
+            "insert into root.db.history (time, at1) values (2000, 2), (3000, 
3)", "flush"),
+        null);
+
+    final Map<String, String> sourceAttributes = new HashMap<>();
+    final Map<String, String> sinkAttributes = new HashMap<>();
+
+    sourceAttributes.put("source.inclusion", "data");
+    sourceAttributes.put("source.start-time", "2000");
+    sourceAttributes.put("source.history.enable", "false");
+    sourceAttributes.put("source.realtime.mode", "stream");
+    sourceAttributes.put("user", "root");
+
+    sinkAttributes.put("sink", "iotdb-thrift-sink");
+    sinkAttributes.put("sink.batch.enable", "false");
+    sinkAttributes.put("sink.ip", receiverIp);
+    sinkAttributes.put("sink.port", Integer.toString(receiverPort));
+
+    try (final SyncConfigNodeIServiceClient client =
+        (SyncConfigNodeIServiceClient) 
senderEnv.getLeaderConfigNodeConnection()) {
+      final TSStatus status =
+          client.createPipe(
+              new TCreatePipeReq("p1", 
sinkAttributes).setExtractorAttributes(sourceAttributes));
+      Assert.assertEquals(TSStatusCode.SUCCESS_STATUS.getStatusCode(), 
status.getCode());
+
+      TestUtils.assertDataAlwaysOnEnv(
+          receiverEnv,
+          "show timeseries root.db.history.**",
+          
"Timeseries,Alias,Database,DataType,Encoding,Compression,Tags,Attributes,Deadband,DeadbandParameters,ViewType,",
+          Collections.emptySet());
+
+      TestUtils.executeNonQueries(
+          senderEnv,
+          Collections.singletonList(
+              "insert into root.db.realtime (time, at1)"
+                  + " values (1000, 1), (2000, 2), (3000, 3)"),
+          null);
+
+      TestUtils.assertDataEventuallyOnEnv(
+          receiverEnv,
+          "select count(at1) from root.db.realtime",
+          "count(root.db.realtime.at1),",
+          Collections.singleton("2,"));
+      TestUtils.assertDataAlwaysOnEnv(
+          receiverEnv,
+          "show timeseries root.db.history.**",
+          
"Timeseries,Alias,Database,DataType,Encoding,Compression,Tags,Attributes,Deadband,DeadbandParameters,ViewType,",
+          Collections.emptySet());
+    }
+  }
+
   @Test
   public void testSourceStartTimeAndEndTimeWorkingWithOrWithoutPattern() 
throws Exception {
     final DataNodeWrapper receiverDataNode = receiverEnv.getDataNodeWrapper(0);
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/source/dataregion/IoTDBDataRegionSource.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/source/dataregion/IoTDBDataRegionSource.java
index 6df5e10d0a2..9ec1e2c34d2 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/source/dataregion/IoTDBDataRegionSource.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/source/dataregion/IoTDBDataRegionSource.java
@@ -172,7 +172,7 @@ public class IoTDBDataRegionSource extends IoTDBSource {
           EXTRACTOR_REALTIME_MODE_BATCH_MODE_VALUE);
     }
 
-    // Validate source.start-time and source.end-time
+    // A global time range takes precedence over a history-specific time range.
     if (validator
             .getParameters()
             .hasAnyAttributes(
@@ -183,20 +183,16 @@ public class IoTDBDataRegionSource extends IoTDBSource {
         && validator
             .getParameters()
             .hasAnyAttributes(
-                EXTRACTOR_HISTORY_ENABLE_KEY,
-                SOURCE_HISTORY_ENABLE_KEY,
                 SOURCE_HISTORY_START_TIME_KEY,
                 EXTRACTOR_HISTORY_START_TIME_KEY,
                 SOURCE_HISTORY_END_TIME_KEY,
                 EXTRACTOR_HISTORY_END_TIME_KEY)) {
       LOGGER.warn(
-          "When {}, {}, {} or {} is specified, specifying {}, {}, {}, {}, {} 
and {} is invalid.",
+          "When {}, {}, {} or {} is specified, specifying {}, {}, {} or {} is 
invalid.",
           SOURCE_START_TIME_KEY,
           EXTRACTOR_START_TIME_KEY,
           SOURCE_END_TIME_KEY,
           EXTRACTOR_END_TIME_KEY,
-          SOURCE_HISTORY_ENABLE_KEY,
-          EXTRACTOR_HISTORY_ENABLE_KEY,
           SOURCE_HISTORY_START_TIME_KEY,
           EXTRACTOR_HISTORY_START_TIME_KEY,
           SOURCE_HISTORY_END_TIME_KEY,
diff --git 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/source/dataregion/historical/PipeHistoricalDataRegionTsFileSource.java
 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/source/dataregion/historical/PipeHistoricalDataRegionTsFileSource.java
index 6ebdebb6efd..25e65ed8be9 100644
--- 
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/source/dataregion/historical/PipeHistoricalDataRegionTsFileSource.java
+++ 
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/pipe/source/dataregion/historical/PipeHistoricalDataRegionTsFileSource.java
@@ -165,13 +165,23 @@ public class PipeHistoricalDataRegionTsFileSource 
implements PipeHistoricalDataR
       }
     }
 
+    // Historical data extraction is enabled in the following cases:
+    // 1. System restarts the pipe. If the pipe is restarted but historical 
data extraction is not
+    // enabled, the pipe will lose some historical data.
+    // 2. Historical extraction is enabled by the user or by default.
+    isHistoricalSourceEnabled =
+        parameters.getBooleanOrDefault(
+                SystemConstant.RESTART_OR_NEWLY_ADDED_KEY,
+                SystemConstant.RESTART_OR_NEWLY_ADDED_DEFAULT_VALUE)
+            || parameters.getBooleanOrDefault(
+                Arrays.asList(EXTRACTOR_HISTORY_ENABLE_KEY, 
SOURCE_HISTORY_ENABLE_KEY),
+                EXTRACTOR_HISTORY_ENABLE_DEFAULT_VALUE);
+
     if (parameters.hasAnyAttributes(
         SOURCE_START_TIME_KEY,
         EXTRACTOR_START_TIME_KEY,
         SOURCE_END_TIME_KEY,
         EXTRACTOR_END_TIME_KEY)) {
-      isHistoricalSourceEnabled = true;
-
       try {
         historicalDataExtractionStartTime =
             parameters.hasAnyAttributes(SOURCE_START_TIME_KEY, 
EXTRACTOR_START_TIME_KEY)
@@ -205,19 +215,6 @@ public class PipeHistoricalDataRegionTsFileSource 
implements PipeHistoricalDataR
       return;
     }
 
-    // Historical data extraction is enabled in the following cases:
-    // 1. System restarts the pipe. If the pipe is restarted but historical 
data extraction is not
-    // enabled, the pipe will lose some historical data.
-    // 2. User may set the EXTRACTOR_HISTORY_START_TIME and 
EXTRACTOR_HISTORY_END_TIME without
-    // enabling the historical data extraction, which may affect the realtime 
data extraction.
-    isHistoricalSourceEnabled =
-        parameters.getBooleanOrDefault(
-                SystemConstant.RESTART_OR_NEWLY_ADDED_KEY,
-                SystemConstant.RESTART_OR_NEWLY_ADDED_DEFAULT_VALUE)
-            || parameters.getBooleanOrDefault(
-                Arrays.asList(EXTRACTOR_HISTORY_ENABLE_KEY, 
SOURCE_HISTORY_ENABLE_KEY),
-                EXTRACTOR_HISTORY_ENABLE_DEFAULT_VALUE);
-
     try {
       historicalDataExtractionStartTime =
           parameters.hasAnyAttributes(
diff --git 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/pipe/source/dataregion/historical/PipeHistoricalDataRegionTsFileSourceTest.java
 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/pipe/source/dataregion/historical/PipeHistoricalDataRegionTsFileSourceTest.java
index a00fc2c19db..003d8f09c54 100644
--- 
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/pipe/source/dataregion/historical/PipeHistoricalDataRegionTsFileSourceTest.java
+++ 
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/pipe/source/dataregion/historical/PipeHistoricalDataRegionTsFileSourceTest.java
@@ -24,10 +24,14 @@ import 
org.apache.iotdb.commons.consensus.index.impl.HybridProgressIndex;
 import org.apache.iotdb.commons.consensus.index.impl.IoTProgressIndex;
 import org.apache.iotdb.commons.consensus.index.impl.RecoverProgressIndex;
 import org.apache.iotdb.commons.consensus.index.impl.SimpleProgressIndex;
+import org.apache.iotdb.commons.pipe.config.constant.PipeSourceConstant;
+import org.apache.iotdb.commons.pipe.config.constant.SystemConstant;
 import org.apache.iotdb.commons.pipe.datastructure.pattern.PrefixPipePattern;
 import org.apache.iotdb.commons.utils.FileUtils;
 import org.apache.iotdb.db.storageengine.dataregion.tsfile.TsFileResource;
 import 
org.apache.iotdb.db.storageengine.dataregion.tsfile.TsFileResourceStatus;
+import org.apache.iotdb.pipe.api.customizer.parameter.PipeParameterValidator;
+import org.apache.iotdb.pipe.api.customizer.parameter.PipeParameters;
 
 import com.google.common.collect.ImmutableMap;
 import org.apache.tsfile.file.metadata.PlainDeviceID;
@@ -38,9 +42,46 @@ import java.io.File;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
 import java.nio.file.Files;
+import java.util.HashMap;
+import java.util.Map;
 
 public class PipeHistoricalDataRegionTsFileSourceTest {
 
+  @Test
+  public void testGlobalTimeRangeRespectsHistoryEnable() throws Exception {
+    final Map<String, String> attributes = new HashMap<>();
+    attributes.put(PipeSourceConstant.SOURCE_START_TIME_KEY, "1000");
+    attributes.put(PipeSourceConstant.SOURCE_HISTORY_ENABLE_KEY, 
Boolean.FALSE.toString());
+
+    final PipeHistoricalDataRegionTsFileSource realtimeOnlySource =
+        new PipeHistoricalDataRegionTsFileSource();
+    realtimeOnlySource.validate(
+        new PipeParameterValidator(new PipeParameters(new 
HashMap<>(attributes))));
+
+    Assert.assertFalse((Boolean) getPrivateField(realtimeOnlySource, 
"isHistoricalSourceEnabled"));
+    Assert.assertEquals(
+        1000L,
+        ((Long) getPrivateField(realtimeOnlySource, 
"historicalDataExtractionStartTime"))
+            .longValue());
+
+    final PipeHistoricalDataRegionTsFileSource defaultSource =
+        new PipeHistoricalDataRegionTsFileSource();
+    attributes.remove(PipeSourceConstant.SOURCE_HISTORY_ENABLE_KEY);
+    defaultSource.validate(
+        new PipeParameterValidator(new PipeParameters(new 
HashMap<>(attributes))));
+
+    Assert.assertTrue((Boolean) getPrivateField(defaultSource, 
"isHistoricalSourceEnabled"));
+
+    final PipeHistoricalDataRegionTsFileSource restartedSource =
+        new PipeHistoricalDataRegionTsFileSource();
+    attributes.put(PipeSourceConstant.SOURCE_HISTORY_ENABLE_KEY, 
Boolean.FALSE.toString());
+    attributes.put(SystemConstant.RESTART_OR_NEWLY_ADDED_KEY, 
Boolean.TRUE.toString());
+    restartedSource.validate(
+        new PipeParameterValidator(new PipeParameters(new 
HashMap<>(attributes))));
+
+    Assert.assertTrue((Boolean) getPrivateField(restartedSource, 
"isHistoricalSourceEnabled"));
+  }
+
   @Test
   public void testMayTsFileContainUnprocessedDataUsesEqualOrAfterCoverage() 
throws Exception {
     final File tempDir = 
Files.createTempDirectory("pipeHistoricalProgressCoverage").toFile();
@@ -166,4 +207,12 @@ public class PipeHistoricalDataRegionTsFileSourceTest {
     field.setAccessible(true);
     field.set(source, value);
   }
+
+  private static Object getPrivateField(
+      final PipeHistoricalDataRegionTsFileSource source, final String 
fieldName)
+      throws ReflectiveOperationException {
+    final Field field = 
PipeHistoricalDataRegionTsFileSource.class.getDeclaredField(fieldName);
+    field.setAccessible(true);
+    return field.get(source);
+  }
 }

Reply via email to