diff --git a/core/src/main/java/io/grpc/internal/RetriableStream.java b/core/src/main/java/io/grpc/internal/RetriableStream.java index 1cb2a668a4..550d0e1c56 100644 --- a/core/src/main/java/io/grpc/internal/RetriableStream.java +++ b/core/src/main/java/io/grpc/internal/RetriableStream.java @@ -1067,6 +1067,10 @@ abstract class RetriableStream implements ClientStream { isThrottled = !throttle.onQualifiedFailureThenCheckIsAboveThreshold(); } } + if (!isFatal && !isThrottled && !status.isOk() + && (pushbackMillis != null && pushbackMillis > 0)) { + pushbackMillis = 0; // We want the retry after a nonfatal error to be immediate + } return new HedgingPlan(!isFatal && !isThrottled, pushbackMillis); } diff --git a/core/src/test/java/io/grpc/internal/RetriableStreamTest.java b/core/src/test/java/io/grpc/internal/RetriableStreamTest.java index 9b1f6284bc..dc3e881717 100644 --- a/core/src/test/java/io/grpc/internal/RetriableStreamTest.java +++ b/core/src/test/java/io/grpc/internal/RetriableStreamTest.java @@ -2518,7 +2518,7 @@ public class RetriableStreamTest { Status.fromCode(NON_FATAL_STATUS_CODE_1), PROCESSED, headers); fakeClock.forwardTime(HEDGING_DELAY_IN_SECONDS, TimeUnit.SECONDS); - inOrder.verifyNoMoreInteractions(); + inOrder.verify(retriableStreamRecorder).newSubstream(anyInt()); fakeClock.forwardTime(1, TimeUnit.SECONDS); assertEquals(1, fakeClock.numPendingTasks());