You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ozone.apache.org by si...@apache.org on 2026/10/23 08:13:03 UTC

(ozone) branch master updated: HDDS-17312. gRPC client read and EC write timeouts are truncated to whole seconds (#11694)

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

smengcl pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git


The following commit(s) were added to refs/heads/master by this push:
     new 19d77b457ef HDDS-17312. gRPC client read and EC write timeouts are truncated to whole seconds (#11694)
19d77b457ef is described below

commit 19d77b457efe7a30d65fa5632a0036e1761bef59
Author: Siyao Meng <50...@users.noreply.github.com>
AuthorDate: Fri Oct 23 01:12:57 2026 -0700

    HDDS-17312. gRPC client read and EC write timeouts are truncated to whole seconds (#11694)
    
    Co-authored-by: Claude Opus 5.5 <no...@anthropic.com>
---
 .../apache/hadoop/hdds/scm/ECXceiverClientGrpc.java |  6 ++----
 .../apache/hadoop/hdds/scm/XceiverClientGrpc.java   | 21 ++++++++++++++++++---
 .../hdds/scm/TestXceiverClientGrpcChannel.java      | 17 +++++++++++++++++
 3 files changed, 37 insertions(+), 7 deletions(-)

diff --git a/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/ECXceiverClientGrpc.java b/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/ECXceiverClientGrpc.java
index 1236de1e8a0..b8438461c24 100644
--- a/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/ECXceiverClientGrpc.java
+++ b/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/ECXceiverClientGrpc.java
@@ -26,7 +26,6 @@
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.concurrent.TimeUnit;
 import org.apache.hadoop.hdds.conf.ConfigurationSource;
 import org.apache.hadoop.hdds.protocol.DatanodeDetails;
 import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos;
@@ -55,9 +54,8 @@ public ECXceiverClientGrpc(
     super(pipeline, config, trustManager);
     this.enableRetries = config.getBoolean(OZONE_CLIENT_EC_GRPC_RETRIES_ENABLED,
         OZONE_CLIENT_EC_GRPC_RETRIES_ENABLED_DEFAULT);
-    setTimeout(config.getTimeDuration(OzoneConfigKeys.
-        OZONE_CLIENT_EC_GRPC_WRITE_TIMEOUT, OzoneConfigKeys
-        .OZONE_CLIENT_EC_GRPC_WRITE_TIMEOUT_DEFAULT, TimeUnit.SECONDS));
+    setTimeout(getTimeoutMillis(config, OzoneConfigKeys.OZONE_CLIENT_EC_GRPC_WRITE_TIMEOUT,
+        OzoneConfigKeys.OZONE_CLIENT_EC_GRPC_WRITE_TIMEOUT_DEFAULT));
   }
 
   /**
diff --git a/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/XceiverClientGrpc.java b/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/XceiverClientGrpc.java
index 9a9a477638f..7c7e465a55f 100644
--- a/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/XceiverClientGrpc.java
+++ b/hadoop-hdds/client/src/main/java/org/apache/hadoop/hdds/scm/XceiverClientGrpc.java
@@ -43,6 +43,7 @@
 import org.apache.hadoop.hdds.HddsUtils;
 import org.apache.hadoop.hdds.client.BlockID;
 import org.apache.hadoop.hdds.conf.ConfigurationSource;
+import org.apache.hadoop.hdds.conf.TimeDurationUtil;
 import org.apache.hadoop.hdds.protocol.DatanodeDetails;
 import org.apache.hadoop.hdds.protocol.DatanodeID;
 import org.apache.hadoop.hdds.protocol.datanode.proto.ContainerProtos;
@@ -122,8 +123,8 @@ public XceiverClientGrpc(Pipeline pipeline, ConfigurationSource config,
     super();
     Objects.requireNonNull(pipeline, "pipeline == null");
     Objects.requireNonNull(config, "config == null");
-    setTimeout(config.getTimeDuration(OzoneConfigKeys.OZONE_CLIENT_READ_TIMEOUT,
-        OzoneConfigKeys.OZONE_CLIENT_READ_TIMEOUT_DEFAULT, TimeUnit.SECONDS));
+    setTimeout(getTimeoutMillis(config, OzoneConfigKeys.OZONE_CLIENT_READ_TIMEOUT,
+        OzoneConfigKeys.OZONE_CLIENT_READ_TIMEOUT_DEFAULT));
     this.streamReadTimeoutNanos = config.getObject(OzoneClientConfig.class)
         .getStreamReadTimeout().toNanos();
     this.pipeline = pipeline;
@@ -770,7 +771,7 @@ public XceiverClientReply sendCommandAsync(
 
     // create a new grpc message stream pair for each call.
     final StreamObserver<ContainerCommandRequestProto> requestObserver =
-        dnChannelInfoMap.get(dnId).getStub().withDeadlineAfter(timeout, TimeUnit.SECONDS)
+        dnChannelInfoMap.get(dnId).getStub().withDeadlineAfter(timeout, TimeUnit.MILLISECONDS)
             .send(new StreamObserver<ContainerCommandResponseProto>() {
               @Override
               public void onNext(ContainerCommandResponseProto value) {
@@ -832,6 +833,20 @@ public ConfigurationSource getConfig() {
     return config;
   }
 
+  /**
+   * Returns the timeout configured by {@code key} in milliseconds.
+   * A value without unit is in seconds, for compatibility.
+   */
+  static long getTimeoutMillis(ConfigurationSource config, String key, String defaultValue) {
+    return TimeDurationUtil.getDuration(key, config.get(key, defaultValue), TimeUnit.SECONDS).toMillis();
+  }
+
+  @VisibleForTesting
+  long getTimeout() {
+    return timeout;
+  }
+
+  /** Sets the deadline of each request in milliseconds. */
   public void setTimeout(long timeout) {
     this.timeout = timeout;
   }
diff --git a/hadoop-hdds/client/src/test/java/org/apache/hadoop/hdds/scm/TestXceiverClientGrpcChannel.java b/hadoop-hdds/client/src/test/java/org/apache/hadoop/hdds/scm/TestXceiverClientGrpcChannel.java
index 7b84dff590d..4ba82cc6465 100644
--- a/hadoop-hdds/client/src/test/java/org/apache/hadoop/hdds/scm/TestXceiverClientGrpcChannel.java
+++ b/hadoop-hdds/client/src/test/java/org/apache/hadoop/hdds/scm/TestXceiverClientGrpcChannel.java
@@ -29,8 +29,10 @@
 import org.apache.hadoop.hdds.protocol.MockDatanodeDetails;
 import org.apache.hadoop.hdds.scm.pipeline.MockPipeline;
 import org.apache.hadoop.hdds.scm.pipeline.Pipeline;
+import org.apache.hadoop.ozone.OzoneConfigKeys;
 import org.apache.ratis.thirdparty.io.grpc.ManagedChannel;
 import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
 import org.junit.jupiter.params.provider.ValueSource;
 
 class TestXceiverClientGrpcChannel {
@@ -60,6 +62,21 @@ void createChannelUsesConfiguredAddress(boolean useHostname) throws IOException,
     }
   }
 
+  @ParameterizedTest(name = "{0}")
+  @CsvSource({"500ms, 500", "1500ms, 1500", "30s, 30000", "45, 45000"})
+  void timeoutIsInMillis(String value, long expectedMillis) throws IOException {
+    OzoneConfiguration conf = new OzoneConfiguration();
+    conf.set(OzoneConfigKeys.OZONE_CLIENT_READ_TIMEOUT, value);
+    conf.set(OzoneConfigKeys.OZONE_CLIENT_EC_GRPC_WRITE_TIMEOUT, value);
+    Pipeline pipeline = MockPipeline.createPipeline(Collections.singletonList(datanodeWithDistinctHostAndIp()));
+
+    try (XceiverClientGrpc client = new XceiverClientGrpc(pipeline, conf);
+         XceiverClientGrpc ecClient = new ECXceiverClientGrpc(pipeline, conf, null)) {
+      assertThat(client.getTimeout()).isEqualTo(expectedMillis);
+      assertThat(ecClient.getTimeout()).isEqualTo(expectedMillis);
+    }
+  }
+
   private static DatanodeDetails datanodeWithDistinctHostAndIp() {
     return MockDatanodeDetails.createDatanodeDetails(
         DatanodeID.randomID(), HOSTNAME, IP_ADDRESS, "/rack");


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@ozone.apache.org
For additional commands, e-mail: commits-help@ozone.apache.org