From 6bba9fdef6a5f162869ca2703dbe1b4f8c5b733c Mon Sep 17 00:00:00 2001 From: Iain Date: Tue, 6 Oct 2026 01:08:42 +0100 Subject: [PATCH 1/2] Zero-pad nanos in gRPC service config durations See gh-51957 Signed-off-by: Iain --- .../boot/grpc/client/autoconfigure/ServiceConfig.java | 3 ++- .../boot/grpc/client/autoconfigure/ServiceConfigTests.java | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/module/spring-boot-grpc-client/src/main/java/org/springframework/boot/grpc/client/autoconfigure/ServiceConfig.java b/module/spring-boot-grpc-client/src/main/java/org/springframework/boot/grpc/client/autoconfigure/ServiceConfig.java index c7520906b23..086db7cb368 100644 --- a/module/spring-boot-grpc-client/src/main/java/org/springframework/boot/grpc/client/autoconfigure/ServiceConfig.java +++ b/module/spring-boot-grpc-client/src/main/java/org/springframework/boot/grpc/client/autoconfigure/ServiceConfig.java @@ -20,6 +20,7 @@ import java.time.Duration; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.Set; @@ -87,7 +88,7 @@ public record ServiceConfig(@Nullable List loadbalancing, @ } static String durationString(Duration duration) { - return duration.getSeconds() + "." + duration.getNano() + "s"; + return String.format(Locale.ROOT, "%d.%09ds", duration.getSeconds(), duration.getNano()); } static String bytesString(DataSize dataSize) { diff --git a/module/spring-boot-grpc-client/src/test/java/org/springframework/boot/grpc/client/autoconfigure/ServiceConfigTests.java b/module/spring-boot-grpc-client/src/test/java/org/springframework/boot/grpc/client/autoconfigure/ServiceConfigTests.java index dff92d54a9d..ed33d5305ce 100644 --- a/module/spring-boot-grpc-client/src/test/java/org/springframework/boot/grpc/client/autoconfigure/ServiceConfigTests.java +++ b/module/spring-boot-grpc-client/src/test/java/org/springframework/boot/grpc/client/autoconfigure/ServiceConfigTests.java @@ -255,7 +255,7 @@ class ServiceConfigTests { method: m-one retry: max-attempts: 2 - initial-backoff: 1m + initial-backoff: 50ms max-backoff: 1h backoff-multiplier: 2.5 per-attempt-receive-timeout: 2s @@ -268,7 +268,7 @@ class ServiceConfigTests { Map serviceMethodMap = getServiceMethodMap(map, true); Object methodInfo = serviceMethodMap.get("s-one/m-one"); assertThat(methodInfo).extracting("retryPolicy.maxAttempts").isEqualTo(2); - assertThat(methodInfo).extracting("retryPolicy.initialBackoffNanos").isEqualTo(Duration.ofMinutes(1).toNanos()); + assertThat(methodInfo).extracting("retryPolicy.initialBackoffNanos").isEqualTo(Duration.ofMillis(50).toNanos()); assertThat(methodInfo).extracting("retryPolicy.maxBackoffNanos").isEqualTo(Duration.ofHours(1).toNanos()); assertThat(methodInfo).extracting("retryPolicy.backoffMultiplier").isEqualTo(2.5); assertThat(methodInfo).extracting("retryPolicy.perAttemptRecvTimeoutNanos") From 5508957eca0c79f896efa531f960870545f1d2c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Nicoll?= Date: Wed, 7 Oct 2026 16:04:17 +0200 Subject: [PATCH 2/2] Polish "Zero-pad nanos in gRPC service config durations" Use the short "s" format when nanos are equal to 0. This prevents extra padding for the most frequent use case. See gh-51957 --- .../boot/grpc/client/autoconfigure/ServiceConfig.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/module/spring-boot-grpc-client/src/main/java/org/springframework/boot/grpc/client/autoconfigure/ServiceConfig.java b/module/spring-boot-grpc-client/src/main/java/org/springframework/boot/grpc/client/autoconfigure/ServiceConfig.java index 086db7cb368..c00b52259f9 100644 --- a/module/spring-boot-grpc-client/src/main/java/org/springframework/boot/grpc/client/autoconfigure/ServiceConfig.java +++ b/module/spring-boot-grpc-client/src/main/java/org/springframework/boot/grpc/client/autoconfigure/ServiceConfig.java @@ -20,7 +20,6 @@ import java.time.Duration; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.Set; @@ -88,7 +87,8 @@ public record ServiceConfig(@Nullable List loadbalancing, @ } static String durationString(Duration duration) { - return String.format(Locale.ROOT, "%d.%09ds", duration.getSeconds(), duration.getNano()); + return (duration.getNano() == 0) ? "%ds".formatted(duration.getSeconds()) + : "%d.%09ds".formatted(duration.getSeconds(), duration.getNano()); } static String bytesString(DataSize dataSize) {