diff --git a/README.md b/README.md
index 35617fbc487..0b4023fab6b 100644
--- a/README.md
+++ b/README.md
@@ -31,8 +31,8 @@ For a guided tour, take a look at the [quick start
guide](https://grpc.io/docs/languages/java/quickstart) or the more explanatory [gRPC
basics](https://grpc.io/docs/languages/java/basics).
-The [examples](https://github.com/grpc/grpc-java/tree/v1.38.0/examples) and the
-[Android example](https://github.com/grpc/grpc-java/tree/v1.38.0/examples/android)
+The [examples](https://github.com/grpc/grpc-java/tree/v1.38.1/examples) and the
+[Android example](https://github.com/grpc/grpc-java/tree/v1.38.1/examples/android)
are standalone projects that showcase the usage of gRPC.
Download
@@ -43,17 +43,17 @@ Download [the JARs][]. Or for Maven with non-Android, add to your `pom.xml`:
io.grpc
grpc-netty-shaded
- 1.38.0
+ 1.38.1
io.grpc
grpc-protobuf
- 1.38.0
+ 1.38.1
io.grpc
grpc-stub
- 1.38.0
+ 1.38.1
org.apache.tomcat
@@ -65,23 +65,23 @@ Download [the JARs][]. Or for Maven with non-Android, add to your `pom.xml`:
Or for Gradle with non-Android, add to your dependencies:
```gradle
-implementation 'io.grpc:grpc-netty-shaded:1.38.0'
-implementation 'io.grpc:grpc-protobuf:1.38.0'
-implementation 'io.grpc:grpc-stub:1.38.0'
+implementation 'io.grpc:grpc-netty-shaded:1.38.1'
+implementation 'io.grpc:grpc-protobuf:1.38.1'
+implementation 'io.grpc:grpc-stub:1.38.1'
compileOnly 'org.apache.tomcat:annotations-api:6.0.53' // necessary for Java 9+
```
For Android client, use `grpc-okhttp` instead of `grpc-netty-shaded` and
`grpc-protobuf-lite` instead of `grpc-protobuf`:
```gradle
-implementation 'io.grpc:grpc-okhttp:1.38.0'
-implementation 'io.grpc:grpc-protobuf-lite:1.38.0'
-implementation 'io.grpc:grpc-stub:1.38.0'
+implementation 'io.grpc:grpc-okhttp:1.38.1'
+implementation 'io.grpc:grpc-protobuf-lite:1.38.1'
+implementation 'io.grpc:grpc-stub:1.38.1'
compileOnly 'org.apache.tomcat:annotations-api:6.0.53' // necessary for Java 9+
```
[the JARs]:
-https://search.maven.org/search?q=g:io.grpc%20AND%20v:1.38.0
+https://search.maven.org/search?q=g:io.grpc%20AND%20v:1.38.1
Development snapshots are available in [Sonatypes's snapshot
repository](https://oss.sonatype.org/content/repositories/snapshots/).
@@ -113,7 +113,7 @@ For protobuf-based codegen integrated with the Maven build system, you can use
com.google.protobuf:protoc:3.12.0:exe:${os.detected.classifier}
grpc-java
- io.grpc:protoc-gen-grpc-java:1.38.0:exe:${os.detected.classifier}
+ io.grpc:protoc-gen-grpc-java:1.38.1:exe:${os.detected.classifier}
@@ -143,7 +143,7 @@ protobuf {
}
plugins {
grpc {
- artifact = 'io.grpc:protoc-gen-grpc-java:1.38.0'
+ artifact = 'io.grpc:protoc-gen-grpc-java:1.38.1'
}
}
generateProtoTasks {
@@ -176,7 +176,7 @@ protobuf {
}
plugins {
grpc {
- artifact = 'io.grpc:protoc-gen-grpc-java:1.38.0'
+ artifact = 'io.grpc:protoc-gen-grpc-java:1.38.1'
}
}
generateProtoTasks {
diff --git a/build.gradle b/build.gradle
index f7a3536abaa..e497e9a9866 100644
--- a/build.gradle
+++ b/build.gradle
@@ -18,7 +18,7 @@ subprojects {
apply plugin: "net.ltgt.errorprone"
group = "io.grpc"
- version = "1.38.0" // CURRENT_GRPC_VERSION
+ version = "1.38.1" // CURRENT_GRPC_VERSION
repositories {
maven { // The google mirror is less flaky than mavenCentral()
diff --git a/compiler/src/test/golden/TestDeprecatedService.java.txt b/compiler/src/test/golden/TestDeprecatedService.java.txt
index 76789b4798b..5cd7814cd52 100644
--- a/compiler/src/test/golden/TestDeprecatedService.java.txt
+++ b/compiler/src/test/golden/TestDeprecatedService.java.txt
@@ -8,7 +8,7 @@ import static io.grpc.MethodDescriptor.generateFullMethodName;
*
*/
@javax.annotation.Generated(
- value = "by gRPC proto compiler (version 1.38.0)",
+ value = "by gRPC proto compiler (version 1.38.1)",
comments = "Source: grpc/testing/compiler/test.proto")
@java.lang.Deprecated
public final class TestDeprecatedServiceGrpc {
diff --git a/compiler/src/test/golden/TestService.java.txt b/compiler/src/test/golden/TestService.java.txt
index 4324b951d18..1578c6a86f2 100644
--- a/compiler/src/test/golden/TestService.java.txt
+++ b/compiler/src/test/golden/TestService.java.txt
@@ -8,7 +8,7 @@ import static io.grpc.MethodDescriptor.generateFullMethodName;
*
*/
@javax.annotation.Generated(
- value = "by gRPC proto compiler (version 1.38.0)",
+ value = "by gRPC proto compiler (version 1.38.1)",
comments = "Source: grpc/testing/compiler/test.proto")
public final class TestServiceGrpc {
diff --git a/compiler/src/testLite/golden/TestDeprecatedService.java.txt b/compiler/src/testLite/golden/TestDeprecatedService.java.txt
index 1bcc06436c1..4a47a1bd3b7 100644
--- a/compiler/src/testLite/golden/TestDeprecatedService.java.txt
+++ b/compiler/src/testLite/golden/TestDeprecatedService.java.txt
@@ -8,7 +8,7 @@ import static io.grpc.MethodDescriptor.generateFullMethodName;
*
*/
@javax.annotation.Generated(
- value = "by gRPC proto compiler (version 1.38.0)",
+ value = "by gRPC proto compiler (version 1.38.1)",
comments = "Source: grpc/testing/compiler/test.proto")
@java.lang.Deprecated
public final class TestDeprecatedServiceGrpc {
diff --git a/compiler/src/testLite/golden/TestService.java.txt b/compiler/src/testLite/golden/TestService.java.txt
index 02e23ca6c94..167a1d27c76 100644
--- a/compiler/src/testLite/golden/TestService.java.txt
+++ b/compiler/src/testLite/golden/TestService.java.txt
@@ -8,7 +8,7 @@ import static io.grpc.MethodDescriptor.generateFullMethodName;
*
*/
@javax.annotation.Generated(
- value = "by gRPC proto compiler (version 1.38.0)",
+ value = "by gRPC proto compiler (version 1.38.1)",
comments = "Source: grpc/testing/compiler/test.proto")
public final class TestServiceGrpc {
diff --git a/core/src/main/java/io/grpc/internal/GrpcUtil.java b/core/src/main/java/io/grpc/internal/GrpcUtil.java
index 9839ac1c3eb..7f655a47a71 100644
--- a/core/src/main/java/io/grpc/internal/GrpcUtil.java
+++ b/core/src/main/java/io/grpc/internal/GrpcUtil.java
@@ -197,7 +197,7 @@ public byte[] parseAsciiString(byte[] serialized) {
public static final Splitter ACCEPT_ENCODING_SPLITTER = Splitter.on(',').trimResults();
- private static final String IMPLEMENTATION_VERSION = "1.38.0"; // CURRENT_GRPC_VERSION
+ private static final String IMPLEMENTATION_VERSION = "1.38.1"; // CURRENT_GRPC_VERSION
/**
* The default timeout in nanos for a keepalive ping request.
diff --git a/cronet/README.md b/cronet/README.md
index 357faa63b18..71bffb6ea14 100644
--- a/cronet/README.md
+++ b/cronet/README.md
@@ -26,7 +26,7 @@ In your app module's `build.gradle` file, include a dependency on both `grpc-cro
Google Play Services Client Library for Cronet
```
-implementation 'io.grpc:grpc-cronet:1.38.0'
+implementation 'io.grpc:grpc-cronet:1.38.1'
implementation 'com.google.android.gms:play-services-cronet:16.0.0'
```
diff --git a/documentation/android-channel-builder.md b/documentation/android-channel-builder.md
index ff6badac848..114d7719fd6 100644
--- a/documentation/android-channel-builder.md
+++ b/documentation/android-channel-builder.md
@@ -36,8 +36,8 @@ In your `build.gradle` file, include a dependency on both `grpc-android` and
`grpc-okhttp`:
```
-implementation 'io.grpc:grpc-android:1.38.0'
-implementation 'io.grpc:grpc-okhttp:1.38.0'
+implementation 'io.grpc:grpc-android:1.38.1'
+implementation 'io.grpc:grpc-okhttp:1.38.1'
```
You also need permission to access the device's network state in your
diff --git a/examples/android/clientcache/app/build.gradle b/examples/android/clientcache/app/build.gradle
index 182f43570d9..f19c4997be7 100644
--- a/examples/android/clientcache/app/build.gradle
+++ b/examples/android/clientcache/app/build.gradle
@@ -34,7 +34,7 @@ android {
protobuf {
protoc { artifact = 'com.google.protobuf:protoc:3.12.0' }
plugins {
- grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.38.0' // CURRENT_GRPC_VERSION
+ grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.38.1' // CURRENT_GRPC_VERSION
}
}
generateProtoTasks {
@@ -54,12 +54,12 @@ dependencies {
implementation 'com.android.support:appcompat-v7:27.0.2'
// You need to build grpc-java to obtain these libraries below.
- implementation 'io.grpc:grpc-okhttp:1.38.0' // CURRENT_GRPC_VERSION
- implementation 'io.grpc:grpc-protobuf-lite:1.38.0' // CURRENT_GRPC_VERSION
- implementation 'io.grpc:grpc-stub:1.38.0' // CURRENT_GRPC_VERSION
+ implementation 'io.grpc:grpc-okhttp:1.38.1' // CURRENT_GRPC_VERSION
+ implementation 'io.grpc:grpc-protobuf-lite:1.38.1' // CURRENT_GRPC_VERSION
+ implementation 'io.grpc:grpc-stub:1.38.1' // CURRENT_GRPC_VERSION
implementation 'org.apache.tomcat:annotations-api:6.0.53'
testImplementation 'junit:junit:4.12'
testImplementation 'com.google.truth:truth:1.0.1'
- testImplementation 'io.grpc:grpc-testing:1.38.0' // CURRENT_GRPC_VERSION
+ testImplementation 'io.grpc:grpc-testing:1.38.1' // CURRENT_GRPC_VERSION
}
diff --git a/examples/android/helloworld/app/build.gradle b/examples/android/helloworld/app/build.gradle
index d131d618cb1..5f4562742a2 100644
--- a/examples/android/helloworld/app/build.gradle
+++ b/examples/android/helloworld/app/build.gradle
@@ -32,7 +32,7 @@ android {
protobuf {
protoc { artifact = 'com.google.protobuf:protoc:3.12.0' }
plugins {
- grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.38.0' // CURRENT_GRPC_VERSION
+ grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.38.1' // CURRENT_GRPC_VERSION
}
}
generateProtoTasks {
@@ -52,8 +52,8 @@ dependencies {
implementation 'com.android.support:appcompat-v7:27.0.2'
// You need to build grpc-java to obtain these libraries below.
- implementation 'io.grpc:grpc-okhttp:1.38.0' // CURRENT_GRPC_VERSION
- implementation 'io.grpc:grpc-protobuf-lite:1.38.0' // CURRENT_GRPC_VERSION
- implementation 'io.grpc:grpc-stub:1.38.0' // CURRENT_GRPC_VERSION
+ implementation 'io.grpc:grpc-okhttp:1.38.1' // CURRENT_GRPC_VERSION
+ implementation 'io.grpc:grpc-protobuf-lite:1.38.1' // CURRENT_GRPC_VERSION
+ implementation 'io.grpc:grpc-stub:1.38.1' // CURRENT_GRPC_VERSION
implementation 'org.apache.tomcat:annotations-api:6.0.53'
}
diff --git a/examples/android/routeguide/app/build.gradle b/examples/android/routeguide/app/build.gradle
index 88caa356c8c..a2d969604d2 100644
--- a/examples/android/routeguide/app/build.gradle
+++ b/examples/android/routeguide/app/build.gradle
@@ -32,7 +32,7 @@ android {
protobuf {
protoc { artifact = 'com.google.protobuf:protoc:3.12.0' }
plugins {
- grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.38.0' // CURRENT_GRPC_VERSION
+ grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.38.1' // CURRENT_GRPC_VERSION
}
}
generateProtoTasks {
@@ -52,8 +52,8 @@ dependencies {
implementation 'com.android.support:appcompat-v7:27.0.2'
// You need to build grpc-java to obtain these libraries below.
- implementation 'io.grpc:grpc-okhttp:1.38.0' // CURRENT_GRPC_VERSION
- implementation 'io.grpc:grpc-protobuf-lite:1.38.0' // CURRENT_GRPC_VERSION
- implementation 'io.grpc:grpc-stub:1.38.0' // CURRENT_GRPC_VERSION
+ implementation 'io.grpc:grpc-okhttp:1.38.1' // CURRENT_GRPC_VERSION
+ implementation 'io.grpc:grpc-protobuf-lite:1.38.1' // CURRENT_GRPC_VERSION
+ implementation 'io.grpc:grpc-stub:1.38.1' // CURRENT_GRPC_VERSION
implementation 'org.apache.tomcat:annotations-api:6.0.53'
}
diff --git a/examples/android/strictmode/app/build.gradle b/examples/android/strictmode/app/build.gradle
index 18a12c920c8..9223231b1c1 100644
--- a/examples/android/strictmode/app/build.gradle
+++ b/examples/android/strictmode/app/build.gradle
@@ -33,7 +33,7 @@ android {
protobuf {
protoc { artifact = 'com.google.protobuf:protoc:3.12.0' }
plugins {
- grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.38.0' // CURRENT_GRPC_VERSION
+ grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.38.1' // CURRENT_GRPC_VERSION
}
}
generateProtoTasks {
@@ -53,8 +53,8 @@ dependencies {
implementation 'com.android.support:appcompat-v7:28.0.0'
// You need to build grpc-java to obtain these libraries below.
- implementation 'io.grpc:grpc-okhttp:1.38.0' // CURRENT_GRPC_VERSION
- implementation 'io.grpc:grpc-protobuf-lite:1.38.0' // CURRENT_GRPC_VERSION
- implementation 'io.grpc:grpc-stub:1.38.0' // CURRENT_GRPC_VERSION
+ implementation 'io.grpc:grpc-okhttp:1.38.1' // CURRENT_GRPC_VERSION
+ implementation 'io.grpc:grpc-protobuf-lite:1.38.1' // CURRENT_GRPC_VERSION
+ implementation 'io.grpc:grpc-stub:1.38.1' // CURRENT_GRPC_VERSION
implementation 'org.apache.tomcat:annotations-api:6.0.53'
}
diff --git a/examples/build.gradle b/examples/build.gradle
index 8064a8f74e3..69973fe0a23 100644
--- a/examples/build.gradle
+++ b/examples/build.gradle
@@ -22,7 +22,7 @@ targetCompatibility = 1.7
// Feel free to delete the comment at the next line. It is just for safely
// updating the version in our release process.
-def grpcVersion = '1.38.0' // CURRENT_GRPC_VERSION
+def grpcVersion = '1.38.1' // CURRENT_GRPC_VERSION
def protobufVersion = '3.12.0'
def protocVersion = protobufVersion
diff --git a/examples/example-alts/build.gradle b/examples/example-alts/build.gradle
index 210aa5c6814..1f84ea2e7de 100644
--- a/examples/example-alts/build.gradle
+++ b/examples/example-alts/build.gradle
@@ -23,7 +23,7 @@ targetCompatibility = 1.7
// Feel free to delete the comment at the next line. It is just for safely
// updating the version in our release process.
-def grpcVersion = '1.38.0' // CURRENT_GRPC_VERSION
+def grpcVersion = '1.38.1' // CURRENT_GRPC_VERSION
def protocVersion = '3.12.0'
dependencies {
diff --git a/examples/example-gauth/build.gradle b/examples/example-gauth/build.gradle
index e4d1290aebb..f0be360ab79 100644
--- a/examples/example-gauth/build.gradle
+++ b/examples/example-gauth/build.gradle
@@ -23,7 +23,7 @@ targetCompatibility = 1.7
// Feel free to delete the comment at the next line. It is just for safely
// updating the version in our release process.
-def grpcVersion = '1.38.0' // CURRENT_GRPC_VERSION
+def grpcVersion = '1.38.1' // CURRENT_GRPC_VERSION
def protobufVersion = '3.12.0'
def protocVersion = protobufVersion
diff --git a/examples/example-gauth/pom.xml b/examples/example-gauth/pom.xml
index bae735250b1..34e9e03e57e 100644
--- a/examples/example-gauth/pom.xml
+++ b/examples/example-gauth/pom.xml
@@ -6,13 +6,13 @@
jar
- 1.38.0
+ 1.38.1
example-gauth
https://github.com/grpc/grpc-java
UTF-8
- 1.38.0
+ 1.38.1
3.12.0
1.7
diff --git a/examples/example-hostname/build.gradle b/examples/example-hostname/build.gradle
index d8ab2a645b6..78809aa2b7c 100644
--- a/examples/example-hostname/build.gradle
+++ b/examples/example-hostname/build.gradle
@@ -21,7 +21,7 @@ targetCompatibility = 1.7
// Feel free to delete the comment at the next line. It is just for safely
// updating the version in our release process.
-def grpcVersion = '1.38.0' // CURRENT_GRPC_VERSION
+def grpcVersion = '1.38.1' // CURRENT_GRPC_VERSION
def protobufVersion = '3.12.0'
dependencies {
diff --git a/examples/example-hostname/pom.xml b/examples/example-hostname/pom.xml
index e02e3ac79f7..0955a348838 100644
--- a/examples/example-hostname/pom.xml
+++ b/examples/example-hostname/pom.xml
@@ -6,13 +6,13 @@
jar
- 1.38.0
+ 1.38.1
example-hostname
https://github.com/grpc/grpc-java
UTF-8
- 1.38.0
+ 1.38.1
3.12.0
1.7
diff --git a/examples/example-jwt-auth/build.gradle b/examples/example-jwt-auth/build.gradle
index 1c20b8e43a4..272816cf4df 100644
--- a/examples/example-jwt-auth/build.gradle
+++ b/examples/example-jwt-auth/build.gradle
@@ -22,7 +22,7 @@ targetCompatibility = 1.7
// Feel free to delete the comment at the next line. It is just for safely
// updating the version in our release process.
-def grpcVersion = '1.38.0' // CURRENT_GRPC_VERSION
+def grpcVersion = '1.38.1' // CURRENT_GRPC_VERSION
def protobufVersion = '3.12.0'
def protocVersion = protobufVersion
diff --git a/examples/example-jwt-auth/pom.xml b/examples/example-jwt-auth/pom.xml
index c3b771b199f..1068bf08523 100644
--- a/examples/example-jwt-auth/pom.xml
+++ b/examples/example-jwt-auth/pom.xml
@@ -7,13 +7,13 @@
jar
- 1.38.0
+ 1.38.1
example-jwt-auth
https://github.com/grpc/grpc-java
UTF-8
- 1.38.0
+ 1.38.1
3.12.0
3.12.0
diff --git a/examples/example-tls/build.gradle b/examples/example-tls/build.gradle
index 3216206ba11..61129af430e 100644
--- a/examples/example-tls/build.gradle
+++ b/examples/example-tls/build.gradle
@@ -23,7 +23,7 @@ targetCompatibility = 1.7
// Feel free to delete the comment at the next line. It is just for safely
// updating the version in our release process.
-def grpcVersion = '1.38.0' // CURRENT_GRPC_VERSION
+def grpcVersion = '1.38.1' // CURRENT_GRPC_VERSION
def protocVersion = '3.12.0'
dependencies {
diff --git a/examples/example-tls/pom.xml b/examples/example-tls/pom.xml
index fa7d105cb96..2377ff7039e 100644
--- a/examples/example-tls/pom.xml
+++ b/examples/example-tls/pom.xml
@@ -6,13 +6,13 @@
jar
- 1.38.0
+ 1.38.1
example-tls
https://github.com/grpc/grpc-java
UTF-8
- 1.38.0
+ 1.38.1
3.12.0
2.0.34.Final
diff --git a/examples/example-xds/build.gradle b/examples/example-xds/build.gradle
index ee361b19096..76c62cdbe92 100644
--- a/examples/example-xds/build.gradle
+++ b/examples/example-xds/build.gradle
@@ -22,7 +22,7 @@ targetCompatibility = 1.7
// Feel free to delete the comment at the next line. It is just for safely
// updating the version in our release process.
-def grpcVersion = '1.38.0' // CURRENT_GRPC_VERSION
+def grpcVersion = '1.38.1' // CURRENT_GRPC_VERSION
def nettyTcNativeVersion = '2.0.31.Final'
def protocVersion = '3.12.0'
diff --git a/examples/pom.xml b/examples/pom.xml
index 8ccc5e5e68e..d518a7d105e 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -6,13 +6,13 @@
jar
- 1.38.0
+ 1.38.1
examples
https://github.com/grpc/grpc-java
UTF-8
- 1.38.0
+ 1.38.1
3.12.0
3.12.0
diff --git a/grpclb/src/main/java/io/grpc/grpclb/GrpclbState.java b/grpclb/src/main/java/io/grpc/grpclb/GrpclbState.java
index 59fa67dc2dc..19bc35b373f 100644
--- a/grpclb/src/main/java/io/grpc/grpclb/GrpclbState.java
+++ b/grpclb/src/main/java/io/grpc/grpclb/GrpclbState.java
@@ -259,11 +259,19 @@ void handleAddresses(
serviceName,
newLbAddressGroups,
newBackendServers);
+ fallbackBackendList = newBackendServers;
if (newLbAddressGroups.isEmpty()) {
- // No balancer address: close existing balancer connection and enter fallback mode
- // immediately.
+ // No balancer address: close existing balancer connection and prepare to enter fallback
+ // mode. If there is no successful backend connection, it enters fallback mode immediately.
+ // Otherwise, fallback does not happen until backend connections are lost. This behavior
+ // might be different from other languages (e.g., existing balancer connection is not
+ // closed in C-core), but we aren't changing it at this time.
shutdownLbComm();
- syncContext.execute(new FallbackModeTask(NO_LB_ADDRESS_PROVIDED_STATUS));
+ if (!usingFallbackBackends) {
+ fallbackReason = NO_LB_ADDRESS_PROVIDED_STATUS;
+ cancelFallbackTimer();
+ maybeUseFallbackBackends();
+ }
} else {
startLbComm(newLbAddressGroups);
// Avoid creating a new RPC just because the addresses were updated, as it can cause a
@@ -281,7 +289,6 @@ void handleAddresses(
TimeUnit.MILLISECONDS, timerService);
}
}
- fallbackBackendList = newBackendServers;
if (usingFallbackBackends) {
// Populate the new fallback backends to round-robin list.
useFallbackBackends();
diff --git a/grpclb/src/test/java/io/grpc/grpclb/GrpclbLoadBalancerTest.java b/grpclb/src/test/java/io/grpc/grpclb/GrpclbLoadBalancerTest.java
index 7dba20be1d0..f664aad0a7a 100644
--- a/grpclb/src/test/java/io/grpc/grpclb/GrpclbLoadBalancerTest.java
+++ b/grpclb/src/test/java/io/grpc/grpclb/GrpclbLoadBalancerTest.java
@@ -1452,8 +1452,11 @@ public void grpclbFallback_breakLbStreamBeforeFallbackTimerExpires() {
public void grpclbFallback_noBalancerAddress() {
InOrder inOrder = inOrder(helper, subchannelPool);
- // Create just backend addresses
- List backendList = createResolvedBackendAddresses(2);
+ // Create 5 distinct backends
+ List backends = createResolvedBackendAddresses(5);
+
+ // Name resolver gives the first two backend addresses
+ List backendList = backends.subList(0, 2);
deliverResolvedAddresses(backendList, Collections.emptyList());
assertThat(logs).containsAtLeast(
@@ -1474,6 +1477,28 @@ public void grpclbFallback_noBalancerAddress() {
.createOobChannel(ArgumentMatchers.anyList(), anyString());
logs.clear();
+ /////////////////////////////////////////////////////////////////////////////////////////
+ // Name resolver sends new resolution results with new backend addr but no balancer addr
+ /////////////////////////////////////////////////////////////////////////////////////////
+ // Name resolver then gives the last three backends
+ backendList = backends.subList(2, 5);
+ deliverResolvedAddresses(backendList, Collections.emptyList());
+
+ assertThat(logs).containsAtLeast(
+ "INFO: [grpclb-] Using fallback backends",
+ "INFO: [grpclb-] "
+ + "Using RR list=[[[FakeSocketAddress-fake-address-2]/{}], "
+ + "[[FakeSocketAddress-fake-address-3]/{}], "
+ + "[[FakeSocketAddress-fake-address-4]/{}]], drop=[null, null, null]",
+ "INFO: [grpclb-] "
+ + "Update balancing state to CONNECTING: picks=[BUFFER_ENTRY], "
+ + "drops=[null, null, null]")
+ .inOrder();
+
+ // Shift to use updated backends
+ fallbackTestVerifyUseOfFallbackBackendLists(inOrder, backendList);
+ logs.clear();
+
///////////////////////////////////////////////////////////////////////////////////////
// Name resolver sends new resolution results without any backend addr or balancer addr
///////////////////////////////////////////////////////////////////////////////////////
diff --git a/xds/src/main/java/io/grpc/xds/internal/certprovider/FileWatcherCertificateProvider.java b/xds/src/main/java/io/grpc/xds/internal/certprovider/FileWatcherCertificateProvider.java
index bbcb521c0d5..b86de55766e 100644
--- a/xds/src/main/java/io/grpc/xds/internal/certprovider/FileWatcherCertificateProvider.java
+++ b/xds/src/main/java/io/grpc/xds/internal/certprovider/FileWatcherCertificateProvider.java
@@ -82,6 +82,7 @@ public void start() {
@Override
public synchronized void close() {
shutdown = true;
+ scheduledExecutorService.shutdownNow();
if (scheduledFuture != null) {
scheduledFuture.cancel(true);
scheduledFuture = null;
diff --git a/xds/src/test/java/io/grpc/xds/internal/certprovider/FileWatcherCertificateProviderTest.java b/xds/src/test/java/io/grpc/xds/internal/certprovider/FileWatcherCertificateProviderTest.java
index 474c05d0489..7ecc02a99ec 100644
--- a/xds/src/test/java/io/grpc/xds/internal/certprovider/FileWatcherCertificateProviderTest.java
+++ b/xds/src/test/java/io/grpc/xds/internal/certprovider/FileWatcherCertificateProviderTest.java
@@ -180,6 +180,7 @@ public void closeDoesNotScheduleNext() throws IOException, CertificateException
.updateCertificate(any(PrivateKey.class), ArgumentMatchers.anyList());
verify(mockWatcher, never()).updateTrustedRoots(ArgumentMatchers.anyList());
verify(timeService, never()).schedule(any(Runnable.class), any(Long.TYPE), any(TimeUnit.class));
+ verify(timeService, times(1)).shutdownNow();
}