Compare commits

...

6 Commits

Author SHA1 Message Date
Kannan J cf78406950 Bump version to 1.66.0 2024-08-06 15:03:52 +00:00
Kannan J 33af0a75fd Update README etc to reference 1.66.0 2024-08-06 14:49:38 +00:00
Jiajing LU 19c9b998b1 xds: XdsClient should unsubscribe on last resource (#11264)
Otherwise, the server will continue sending updates and if we
re-subscribe to the last resource, the server won't re-send it. Also
completely remove the per-type state, as it could only add confusion.
2024-08-02 12:31:46 -07:00
Kannan J 752a045f10
Revert "Start 1.67.0 development cycle (#11416)" (#11428)
This reverts commit 0090a52 since 1.67.0-SNAPSHOT should not be referenced in the 1.66.x release.
2024-08-02 21:10:43 +05:30
Eric Anderson ef09d94fe8
Revert "Introduce onResult2 in NameResolver Listener2 that returns Status (#11313)" (#11423)
This reverts commit 9ba2f9dec5.

It causes a channel panic due to unimplemented onResult2().

```
java.lang.UnsupportedOperationException: Not implemented.
        at io.grpc.NameResolver$Listener2.onResult2(NameResolver.java:257)
        at io.grpc.internal.DnsNameResolver$Resolve.lambda$run$0(DnsNameResolver.java:334)
        at io.grpc.SynchronizationContext.drain(SynchronizationContext.java:94)
        at io.grpc.SynchronizationContext.execute(SynchronizationContext.java:126)
	at io.grpc.internal.DnsNameResolver$Resolve.run(DnsNameResolver.java:333)
```

b/356669977
2024-08-01 13:38:30 +05:30
Kannan J c37fb181a4 Start 1.67.0 development cycle 2024-07-29 08:46:25 +00:00
44 changed files with 299 additions and 581 deletions

View File

@ -2,7 +2,7 @@ module(
name = "grpc-java",
compatibility_level = 0,
repo_name = "io_grpc_grpc_java",
version = "1.66.0-SNAPSHOT", # CURRENT_GRPC_VERSION
version = "1.66.0", # CURRENT_GRPC_VERSION
)
# GRPC_DEPS_START

View File

@ -44,8 +44,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.65.0/examples) and the
[Android example](https://github.com/grpc/grpc-java/tree/v1.65.0/examples/android)
The [examples](https://github.com/grpc/grpc-java/tree/v1.66.0/examples) and the
[Android example](https://github.com/grpc/grpc-java/tree/v1.66.0/examples/android)
are standalone projects that showcase the usage of gRPC.
Download
@ -56,18 +56,18 @@ Download [the JARs][]. Or for Maven with non-Android, add to your `pom.xml`:
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty-shaded</artifactId>
<version>1.65.0</version>
<version>1.66.0</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>1.65.0</version>
<version>1.66.0</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>1.65.0</version>
<version>1.66.0</version>
</dependency>
<dependency> <!-- necessary for Java 9+ -->
<groupId>org.apache.tomcat</groupId>
@ -79,18 +79,18 @@ 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
runtimeOnly 'io.grpc:grpc-netty-shaded:1.65.0'
implementation 'io.grpc:grpc-protobuf:1.65.0'
implementation 'io.grpc:grpc-stub:1.65.0'
runtimeOnly 'io.grpc:grpc-netty-shaded:1.66.0'
implementation 'io.grpc:grpc-protobuf:1.66.0'
implementation 'io.grpc:grpc-stub:1.66.0'
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.65.0'
implementation 'io.grpc:grpc-protobuf-lite:1.65.0'
implementation 'io.grpc:grpc-stub:1.65.0'
implementation 'io.grpc:grpc-okhttp:1.66.0'
implementation 'io.grpc:grpc-protobuf-lite:1.66.0'
implementation 'io.grpc:grpc-stub:1.66.0'
compileOnly 'org.apache.tomcat:annotations-api:6.0.53' // necessary for Java 9+
```
@ -99,7 +99,7 @@ For [Bazel](https://bazel.build), you can either
(with the GAVs from above), or use `@io_grpc_grpc_java//api` et al (see below).
[the JARs]:
https://search.maven.org/search?q=g:io.grpc%20AND%20v:1.65.0
https://search.maven.org/search?q=g:io.grpc%20AND%20v:1.66.0
Development snapshots are available in [Sonatypes's snapshot
repository](https://oss.sonatype.org/content/repositories/snapshots/).
@ -129,9 +129,9 @@ For protobuf-based codegen integrated with the Maven build system, you can use
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.6.1</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:3.25.1:exe:${os.detected.classifier}</protocArtifact>
<protocArtifact>com.google.protobuf:protoc:3.25.3:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.65.0:exe:${os.detected.classifier}</pluginArtifact>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.66.0:exe:${os.detected.classifier}</pluginArtifact>
</configuration>
<executions>
<execution>
@ -157,11 +157,11 @@ plugins {
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:3.25.1"
artifact = "com.google.protobuf:protoc:3.25.3"
}
plugins {
grpc {
artifact = 'io.grpc:protoc-gen-grpc-java:1.65.0'
artifact = 'io.grpc:protoc-gen-grpc-java:1.66.0'
}
}
generateProtoTasks {
@ -190,11 +190,11 @@ plugins {
protobuf {
protoc {
artifact = "com.google.protobuf:protoc:3.25.1"
artifact = "com.google.protobuf:protoc:3.25.3"
}
plugins {
grpc {
artifact = 'io.grpc:protoc-gen-grpc-java:1.65.0'
artifact = 'io.grpc:protoc-gen-grpc-java:1.66.0'
}
}
generateProtoTasks {

View File

@ -246,16 +246,6 @@ public abstract class NameResolver {
*/
@Override
public abstract void onError(Status error);
/**
* Handles updates on resolved addresses and attributes.
*
* @param resolutionResult the resolved server addresses, attributes, and Service Config.
* @since 1.66
*/
public Status onResult2(ResolutionResult resolutionResult) {
throw new UnsupportedOperationException("Not implemented.");
}
}
/**

View File

@ -21,7 +21,7 @@ subprojects {
apply plugin: "net.ltgt.errorprone"
group = "io.grpc"
version = "1.66.0-SNAPSHOT" // CURRENT_GRPC_VERSION
version = "1.66.0" // CURRENT_GRPC_VERSION
repositories {
maven { // The google mirror is less flaky than mavenCentral()

View File

@ -8,7 +8,7 @@ import static io.grpc.MethodDescriptor.generateFullMethodName;
* </pre>
*/
@javax.annotation.Generated(
value = "by gRPC proto compiler (version 1.66.0-SNAPSHOT)",
value = "by gRPC proto compiler (version 1.66.0)",
comments = "Source: grpc/testing/compiler/test.proto")
@io.grpc.stub.annotations.GrpcGenerated
@java.lang.Deprecated

View File

@ -8,7 +8,7 @@ import static io.grpc.MethodDescriptor.generateFullMethodName;
* </pre>
*/
@javax.annotation.Generated(
value = "by gRPC proto compiler (version 1.66.0-SNAPSHOT)",
value = "by gRPC proto compiler (version 1.66.0)",
comments = "Source: grpc/testing/compiler/test.proto")
@io.grpc.stub.annotations.GrpcGenerated
public final class TestServiceGrpc {

View File

@ -330,9 +330,7 @@ public class DnsNameResolver extends NameResolver {
resolutionResultBuilder.setAttributes(result.attributes);
}
}
syncContext.execute(() -> {
savedListener.onResult2(resolutionResultBuilder.build());
});
savedListener.onResult(resolutionResultBuilder.build());
} catch (IOException e) {
savedListener.onError(
Status.UNAVAILABLE.withDescription("Unable to resolve host " + host).withCause(e));

View File

@ -219,7 +219,7 @@ public final class GrpcUtil {
public static final Splitter ACCEPT_ENCODING_SPLITTER = Splitter.on(',').trimResults();
public static final String IMPLEMENTATION_VERSION = "1.66.0-SNAPSHOT"; // CURRENT_GRPC_VERSION
public static final String IMPLEMENTATION_VERSION = "1.66.0"; // CURRENT_GRPC_VERSION
/**
* The default timeout in nanos for a keepalive ping request.

View File

@ -1673,24 +1673,11 @@ final class ManagedChannelImpl extends ManagedChannel implements
public void onResult(final ResolutionResult resolutionResult) {
final class NamesResolved implements Runnable {
@Override
public void run() {
Status status = onResult2(resolutionResult);
ResolutionResultListener resolutionResultListener = resolutionResult.getAttributes()
.get(RetryingNameResolver.RESOLUTION_RESULT_LISTENER_KEY);
resolutionResultListener.resolutionAttempted(status);
}
}
syncContext.execute(new NamesResolved());
}
@SuppressWarnings("ReferenceEquality")
@Override
public Status onResult2(final ResolutionResult resolutionResult) {
syncContext.throwIfNotInThisSynchronizationContext();
public void run() {
if (ManagedChannelImpl.this.nameResolver != resolver) {
return Status.OK;
return;
}
List<EquivalentAddressGroup> servers = resolutionResult.getAddresses();
@ -1706,6 +1693,8 @@ final class ManagedChannelImpl extends ManagedChannel implements
}
ConfigOrError configOrError = resolutionResult.getServiceConfig();
ResolutionResultListener resolutionResultListener = resolutionResult.getAttributes()
.get(RetryingNameResolver.RESOLUTION_RESULT_LISTENER_KEY);
InternalConfigSelector resolvedConfigSelector =
resolutionResult.getAttributes().get(InternalConfigSelector.KEY);
ManagedChannelServiceConfig validServiceConfig =
@ -1762,7 +1751,10 @@ final class ManagedChannelImpl extends ManagedChannel implements
// we later check for these error codes when investigating pick results in
// GrpcUtil.getTransportFromPickResult().
onError(configOrError.getError());
return configOrError.getError();
if (resolutionResultListener != null) {
resolutionResultListener.resolutionAttempted(configOrError.getError());
}
return;
} else {
effectiveServiceConfig = lastServiceConfig;
}
@ -1806,14 +1798,21 @@ final class ManagedChannelImpl extends ManagedChannel implements
}
Attributes attributes = attrBuilder.build();
return helper.lb.tryAcceptResolvedAddresses(
Status addressAcceptanceStatus = helper.lb.tryAcceptResolvedAddresses(
ResolvedAddresses.newBuilder()
.setAddresses(servers)
.setAttributes(attributes)
.setLoadBalancingPolicyConfig(effectiveServiceConfig.getLoadBalancingConfig())
.build());
// If a listener is provided, let it know if the addresses were accepted.
if (resolutionResultListener != null) {
resolutionResultListener.resolutionAttempted(addressAcceptanceStatus);
}
return Status.OK;
}
}
}
syncContext.execute(new NamesResolved());
}
@Override

View File

@ -95,24 +95,12 @@ final class RetryingNameResolver extends ForwardingNameResolver {
"RetryingNameResolver can only be used once to wrap a NameResolver");
}
// To have retry behavior for name resolvers that haven't migrated to onResult2.
delegateListener.onResult(resolutionResult.toBuilder().setAttributes(
resolutionResult.getAttributes().toBuilder()
.set(RESOLUTION_RESULT_LISTENER_KEY, new ResolutionResultListener()).build())
.build());
}
@Override
public Status onResult2(ResolutionResult resolutionResult) {
Status status = delegateListener.onResult2(resolutionResult);
if (status.isOk()) {
retryScheduler.reset();
} else {
retryScheduler.schedule(new DelayedNameResolverRefresh());
}
return status;
}
@Override
public void onError(Status error) {
delegateListener.onError(error);

View File

@ -26,6 +26,7 @@ import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.isA;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
@ -225,7 +226,13 @@ public class DnsNameResolverTest {
System.getProperty(DnsNameResolver.NETWORKADDRESS_CACHE_TTL_PROPERTY);
// By default the mock listener processes the result successfully.
when(mockListener.onResult2(isA(ResolutionResult.class))).thenReturn(Status.OK);
doAnswer(invocation -> {
ResolutionResult result = invocation.getArgument(0);
syncContext.execute(
() -> result.getAttributes().get(RetryingNameResolver.RESOLUTION_RESULT_LISTENER_KEY)
.resolutionAttempted(Status.OK));
return null;
}).when(mockListener).onResult(isA(ResolutionResult.class));
}
@After
@ -312,13 +319,13 @@ public class DnsNameResolverTest {
resolver.start(mockListener);
assertEquals(1, fakeExecutor.runDueTasks());
verify(mockListener).onResult2(resultCaptor.capture());
verify(mockListener).onResult(resultCaptor.capture());
assertAnswerMatches(answer1, 81, resultCaptor.getValue());
assertEquals(0, fakeClock.numPendingTasks());
resolver.refresh();
assertEquals(1, fakeExecutor.runDueTasks());
verify(mockListener, times(2)).onResult2(resultCaptor.capture());
verify(mockListener, times(2)).onResult(resultCaptor.capture());
assertAnswerMatches(answer2, 81, resultCaptor.getValue());
assertEquals(0, fakeClock.numPendingTasks());
assertEquals(0, fakeExecutor.numPendingTasks());
@ -340,7 +347,7 @@ public class DnsNameResolverTest {
resolver.start(mockListener);
assertEquals(1, fakeExecutor.runDueTasks());
verify(mockListener).onResult2(resultCaptor.capture());
verify(mockListener).onResult(resultCaptor.capture());
assertAnswerMatches(answer, 81, resultCaptor.getValue());
assertEquals(0, fakeClock.numPendingTasks());
assertEquals(0, fakeExecutor.numPendingTasks());
@ -382,7 +389,7 @@ public class DnsNameResolverTest {
resolver.start(mockListener);
assertEquals(0, fakeExecutor.runDueTasks());
verify(mockListener).onResult2(resultCaptor.capture());
verify(mockListener).onResult(resultCaptor.capture());
assertAnswerMatches(answer, 81, resultCaptor.getValue());
assertEquals(0, fakeClock.numPendingTasks());
assertEquals(0, fakeExecutor.numPendingTasks());
@ -411,7 +418,7 @@ public class DnsNameResolverTest {
resolver.start(mockListener);
assertEquals(1, fakeExecutor.runDueTasks());
verify(mockListener).onResult2(resultCaptor.capture());
verify(mockListener).onResult(resultCaptor.capture());
assertAnswerMatches(answer1, 81, resultCaptor.getValue());
assertEquals(0, fakeClock.numPendingTasks());
@ -445,7 +452,7 @@ public class DnsNameResolverTest {
resolver.start(mockListener);
assertEquals(1, fakeExecutor.runDueTasks());
verify(mockListener).onResult2(resultCaptor.capture());
verify(mockListener).onResult(resultCaptor.capture());
assertAnswerMatches(answer, 81, resultCaptor.getValue());
assertEquals(0, fakeClock.numPendingTasks());
@ -480,14 +487,14 @@ public class DnsNameResolverTest {
resolver.start(mockListener);
assertEquals(1, fakeExecutor.runDueTasks());
verify(mockListener).onResult2(resultCaptor.capture());
verify(mockListener).onResult(resultCaptor.capture());
assertAnswerMatches(answer1, 81, resultCaptor.getValue());
assertEquals(0, fakeClock.numPendingTasks());
fakeTicker.advance(ttl + 1, TimeUnit.SECONDS);
resolver.refresh();
assertEquals(1, fakeExecutor.runDueTasks());
verify(mockListener, times(2)).onResult2(resultCaptor.capture());
verify(mockListener, times(2)).onResult(resultCaptor.capture());
assertAnswerMatches(answer2, 81, resultCaptor.getValue());
assertEquals(0, fakeClock.numPendingTasks());
assertEquals(0, fakeExecutor.numPendingTasks());
@ -524,7 +531,7 @@ public class DnsNameResolverTest {
resolver.start(mockListener);
assertEquals(1, fakeExecutor.runDueTasks());
verify(mockListener).onResult2(resultCaptor.capture());
verify(mockListener).onResult(resultCaptor.capture());
assertAnswerMatches(answer1, 81, resultCaptor.getValue());
assertEquals(0, fakeClock.numPendingTasks());
@ -537,7 +544,7 @@ public class DnsNameResolverTest {
fakeTicker.advance(1, TimeUnit.SECONDS);
resolver.refresh();
assertEquals(1, fakeExecutor.runDueTasks());
verify(mockListener, times(2)).onResult2(resultCaptor.capture());
verify(mockListener, times(2)).onResult(resultCaptor.capture());
assertAnswerMatches(answer2, 81, resultCaptor.getValue());
assertEquals(0, fakeClock.numPendingTasks());
assertEquals(0, fakeExecutor.numPendingTasks());
@ -568,7 +575,7 @@ public class DnsNameResolverTest {
assertThat(fakeExecutor.runDueTasks()).isEqualTo(1);
ArgumentCaptor<ResolutionResult> ac = ArgumentCaptor.forClass(ResolutionResult.class);
verify(mockListener).onResult2(ac.capture());
verify(mockListener).onResult(ac.capture());
verifyNoMoreInteractions(mockListener);
assertThat(ac.getValue().getAddresses()).isEmpty();
assertThat(ac.getValue().getServiceConfig()).isNull();
@ -581,7 +588,12 @@ public class DnsNameResolverTest {
// Load balancer rejects the empty addresses.
@Test
public void resolve_emptyResult_notAccepted() throws Exception {
when(mockListener.onResult2(isA(ResolutionResult.class))).thenReturn(Status.UNAVAILABLE);
doAnswer(invocation -> {
ResolutionResult result = invocation.getArgument(0);
result.getAttributes().get(RetryingNameResolver.RESOLUTION_RESULT_LISTENER_KEY)
.resolutionAttempted(Status.UNAVAILABLE);
return null;
}).when(mockListener).onResult(isA(ResolutionResult.class));
DnsNameResolver.enableTxt = true;
RetryingNameResolver resolver = newResolver("dns:///addr.fake:1234", 443);
@ -602,7 +614,7 @@ public class DnsNameResolverTest {
syncContext.execute(() -> assertThat(fakeExecutor.runDueTasks()).isEqualTo(1));
ArgumentCaptor<ResolutionResult> ac = ArgumentCaptor.forClass(ResolutionResult.class);
verify(mockListener).onResult2(ac.capture());
verify(mockListener).onResult(ac.capture());
verifyNoMoreInteractions(mockListener);
assertThat(ac.getValue().getAddresses()).isEmpty();
assertThat(ac.getValue().getServiceConfig()).isNull();
@ -628,7 +640,7 @@ public class DnsNameResolverTest {
dnsResolver.setResourceResolver(null);
resolver.start(mockListener);
assertEquals(1, fakeExecutor.runDueTasks());
verify(mockListener).onResult2(resultCaptor.capture());
verify(mockListener).onResult(resultCaptor.capture());
ResolutionResult result = resultCaptor.getValue();
InetSocketAddress resolvedBackendAddr =
(InetSocketAddress) Iterables.getOnlyElement(
@ -700,7 +712,7 @@ public class DnsNameResolverTest {
resolver.start(mockListener);
assertEquals(1, fakeExecutor.runDueTasks());
verify(mockListener).onResult2(resultCaptor.capture());
verify(mockListener).onResult(resultCaptor.capture());
ResolutionResult result = resultCaptor.getValue();
InetSocketAddress resolvedBackendAddr =
(InetSocketAddress) Iterables.getOnlyElement(
@ -758,7 +770,7 @@ public class DnsNameResolverTest {
dnsResolver.setResourceResolver(mockResourceResolver);
resolver.start(mockListener);
assertEquals(1, fakeExecutor.runDueTasks());
verify(mockListener).onResult2(resultCaptor.capture());
verify(mockListener).onResult(resultCaptor.capture());
ResolutionResult result = resultCaptor.getValue();
InetSocketAddress resolvedBackendAddr =
(InetSocketAddress) Iterables.getOnlyElement(
@ -790,7 +802,7 @@ public class DnsNameResolverTest {
dnsResolver.setResourceResolver(mockResourceResolver);
resolver.start(mockListener);
assertEquals(1, fakeExecutor.runDueTasks());
verify(mockListener).onResult2(resultCaptor.capture());
verify(mockListener).onResult(resultCaptor.capture());
ResolutionResult result = resultCaptor.getValue();
InetSocketAddress resolvedBackendAddr =
(InetSocketAddress) Iterables.getOnlyElement(
@ -858,7 +870,7 @@ public class DnsNameResolverTest {
resolver.start(mockListener);
assertEquals(1, fakeExecutor.runDueTasks());
verify(mockListener).onResult2(resultCaptor.capture());
verify(mockListener).onResult(resultCaptor.capture());
List<EquivalentAddressGroup> result = resultCaptor.getValue().getAddresses();
assertThat(result).hasSize(1);
EquivalentAddressGroup eag = result.get(0);

View File

@ -1054,79 +1054,6 @@ public class ManagedChannelImplTest {
verifyNoMoreInteractions(mockLoadBalancer);
}
@Test
public void noMoreCallbackAfterLoadBalancerShutdown_configError() throws InterruptedException {
FakeNameResolverFactory nameResolverFactory =
new FakeNameResolverFactory.Builder(expectedUri)
.setServers(Collections.singletonList(new EquivalentAddressGroup(socketAddress)))
.build();
channelBuilder.nameResolverFactory(nameResolverFactory);
Status resolutionError = Status.UNAVAILABLE.withDescription("Resolution failed");
createChannel();
FakeNameResolverFactory.FakeNameResolver resolver = nameResolverFactory.resolvers.get(0);
verify(mockLoadBalancerProvider).newLoadBalancer(any(Helper.class));
verify(mockLoadBalancer).acceptResolvedAddresses(resolvedAddressCaptor.capture());
assertThat(resolvedAddressCaptor.getValue().getAddresses()).containsExactly(addressGroup);
SubchannelStateListener stateListener1 = mock(SubchannelStateListener.class);
SubchannelStateListener stateListener2 = mock(SubchannelStateListener.class);
Subchannel subchannel1 =
createSubchannelSafely(helper, addressGroup, Attributes.EMPTY, stateListener1);
Subchannel subchannel2 =
createSubchannelSafely(helper, addressGroup, Attributes.EMPTY, stateListener2);
requestConnectionSafely(helper, subchannel1);
requestConnectionSafely(helper, subchannel2);
verify(mockTransportFactory, times(2))
.newClientTransport(
any(SocketAddress.class), any(ClientTransportOptions.class), any(ChannelLogger.class));
MockClientTransportInfo transportInfo1 = transports.poll();
MockClientTransportInfo transportInfo2 = transports.poll();
// LoadBalancer receives all sorts of callbacks
transportInfo1.listener.transportReady();
verify(stateListener1, times(2)).onSubchannelState(stateInfoCaptor.capture());
assertSame(CONNECTING, stateInfoCaptor.getAllValues().get(0).getState());
assertSame(READY, stateInfoCaptor.getAllValues().get(1).getState());
verify(stateListener2).onSubchannelState(stateInfoCaptor.capture());
assertSame(CONNECTING, stateInfoCaptor.getValue().getState());
resolver.listener.onError(resolutionError);
verify(mockLoadBalancer).handleNameResolutionError(resolutionError);
verifyNoMoreInteractions(mockLoadBalancer);
channel.shutdown();
verify(mockLoadBalancer).shutdown();
verifyNoMoreInteractions(stateListener1, stateListener2);
// LoadBalancer will normally shutdown all subchannels
shutdownSafely(helper, subchannel1);
shutdownSafely(helper, subchannel2);
// Since subchannels are shutdown, SubchannelStateListeners will only get SHUTDOWN regardless of
// the transport states.
transportInfo1.listener.transportShutdown(Status.UNAVAILABLE);
transportInfo2.listener.transportReady();
verify(stateListener1).onSubchannelState(ConnectivityStateInfo.forNonError(SHUTDOWN));
verify(stateListener2).onSubchannelState(ConnectivityStateInfo.forNonError(SHUTDOWN));
verifyNoMoreInteractions(stateListener1, stateListener2);
// No more callback should be delivered to LoadBalancer after it's shut down
resolver.listener.onResult(
ResolutionResult.newBuilder()
.setAddresses(new ArrayList<>())
.setServiceConfig(
ConfigOrError.fromError(Status.UNAVAILABLE.withDescription("Resolution failed")))
.build());
Thread.sleep(1100);
assertThat(timer.getPendingTasks()).isEmpty();
resolver.resolved();
verifyNoMoreInteractions(mockLoadBalancer);
}
@Test
public void interceptor() throws Exception {
final AtomicLong atomic = new AtomicLong();
@ -3211,48 +3138,6 @@ public class ManagedChannelImplTest {
assertThat(getStats(channel).channelTrace.events).hasSize(prevSize + 1);
}
@Test
public void channelTracing_nameResolvedEvent_zeorAndNonzeroBackends_usesListener2onResult2()
throws Exception {
timer.forwardNanos(1234);
channelBuilder.maxTraceEvents(10);
List<EquivalentAddressGroup> servers = new ArrayList<>();
servers.add(new EquivalentAddressGroup(socketAddress));
FakeNameResolverFactory nameResolverFactory =
new FakeNameResolverFactory.Builder(expectedUri).setServers(servers).build();
channelBuilder.nameResolverFactory(nameResolverFactory);
createChannel();
int prevSize = getStats(channel).channelTrace.events.size();
ResolutionResult resolutionResult1 = ResolutionResult.newBuilder()
.setAddresses(Collections.singletonList(
new EquivalentAddressGroup(
Arrays.asList(new SocketAddress() {}, new SocketAddress() {}))))
.build();
channel.syncContext.execute(
() -> nameResolverFactory.resolvers.get(0).listener.onResult2(resolutionResult1));
assertThat(getStats(channel).channelTrace.events).hasSize(prevSize);
prevSize = getStats(channel).channelTrace.events.size();
nameResolverFactory.resolvers.get(0).listener.onError(Status.INTERNAL);
assertThat(getStats(channel).channelTrace.events).hasSize(prevSize + 1);
prevSize = getStats(channel).channelTrace.events.size();
nameResolverFactory.resolvers.get(0).listener.onError(Status.INTERNAL);
assertThat(getStats(channel).channelTrace.events).hasSize(prevSize);
prevSize = getStats(channel).channelTrace.events.size();
ResolutionResult resolutionResult2 = ResolutionResult.newBuilder()
.setAddresses(Collections.singletonList(
new EquivalentAddressGroup(
Arrays.asList(new SocketAddress() {}, new SocketAddress() {}))))
.build();
channel.syncContext.execute(
() -> nameResolverFactory.resolvers.get(0).listener.onResult2(resolutionResult2));
assertThat(getStats(channel).channelTrace.events).hasSize(prevSize + 1);
}
@Test
public void channelTracing_serviceConfigChange() throws Exception {
timer.forwardNanos(1234);
@ -3312,69 +3197,6 @@ public class ManagedChannelImplTest {
.build());
}
@Test
public void channelTracing_serviceConfigChange_usesListener2OnResult2() throws Exception {
timer.forwardNanos(1234);
channelBuilder.maxTraceEvents(10);
List<EquivalentAddressGroup> servers = new ArrayList<>();
servers.add(new EquivalentAddressGroup(socketAddress));
FakeNameResolverFactory nameResolverFactory =
new FakeNameResolverFactory.Builder(expectedUri).setServers(servers).build();
channelBuilder.nameResolverFactory(nameResolverFactory);
createChannel();
int prevSize = getStats(channel).channelTrace.events.size();
ManagedChannelServiceConfig mcsc1 = createManagedChannelServiceConfig(
ImmutableMap.<String, Object>of(),
new PolicySelection(
mockLoadBalancerProvider, null));
ResolutionResult resolutionResult1 = ResolutionResult.newBuilder()
.setAddresses(Collections.singletonList(
new EquivalentAddressGroup(
Arrays.asList(new SocketAddress() {}, new SocketAddress() {}))))
.setServiceConfig(ConfigOrError.fromConfig(mcsc1))
.build();
channel.syncContext.execute(() ->
nameResolverFactory.resolvers.get(0).listener.onResult2(resolutionResult1));
assertThat(getStats(channel).channelTrace.events).hasSize(prevSize + 1);
assertThat(getStats(channel).channelTrace.events.get(prevSize))
.isEqualTo(new ChannelTrace.Event.Builder()
.setDescription("Service config changed")
.setSeverity(ChannelTrace.Event.Severity.CT_INFO)
.setTimestampNanos(timer.getTicker().read())
.build());
prevSize = getStats(channel).channelTrace.events.size();
ResolutionResult resolutionResult2 = ResolutionResult.newBuilder().setAddresses(
Collections.singletonList(
new EquivalentAddressGroup(
Arrays.asList(new SocketAddress() {}, new SocketAddress() {}))))
.setServiceConfig(ConfigOrError.fromConfig(mcsc1))
.build();
channel.syncContext.execute(() ->
nameResolverFactory.resolvers.get(0).listener.onResult(resolutionResult2));
assertThat(getStats(channel).channelTrace.events).hasSize(prevSize);
prevSize = getStats(channel).channelTrace.events.size();
timer.forwardNanos(1234);
ResolutionResult resolutionResult3 = ResolutionResult.newBuilder()
.setAddresses(Collections.singletonList(
new EquivalentAddressGroup(
Arrays.asList(new SocketAddress() {}, new SocketAddress() {}))))
.setServiceConfig(ConfigOrError.fromConfig(ManagedChannelServiceConfig.empty()))
.build();
channel.syncContext.execute(() ->
nameResolverFactory.resolvers.get(0).listener.onResult(resolutionResult3));
assertThat(getStats(channel).channelTrace.events).hasSize(prevSize + 1);
assertThat(getStats(channel).channelTrace.events.get(prevSize))
.isEqualTo(new ChannelTrace.Event.Builder()
.setDescription("Service config changed")
.setSeverity(ChannelTrace.Event.Severity.CT_INFO)
.setTimestampNanos(timer.getTicker().read())
.build());
}
@Test
public void channelTracing_stateChangeEvent() throws Exception {
channelBuilder.maxTraceEvents(10);
@ -4035,120 +3857,6 @@ public class ManagedChannelImplTest {
mychannel.shutdownNow();
}
@Test
public void badServiceConfigIsRecoverable_usesListener2OnResult2() throws Exception {
final List<EquivalentAddressGroup> addresses =
ImmutableList.of(new EquivalentAddressGroup(new SocketAddress() {}));
final class FakeNameResolver extends NameResolver {
Listener2 listener;
private final SynchronizationContext syncContext;
FakeNameResolver(Args args) {
this.syncContext = args.getSynchronizationContext();
}
@Override
public String getServiceAuthority() {
return "also fake";
}
@Override
public void start(Listener2 listener) {
this.listener = listener;
syncContext.execute(() ->
listener.onResult2(
ResolutionResult.newBuilder()
.setAddresses(addresses)
.setServiceConfig(
ConfigOrError.fromError(
Status.INTERNAL.withDescription("kaboom is invalid")))
.build()));
}
@Override
public void shutdown() {}
}
final class FakeNameResolverFactory2 extends NameResolver.Factory {
FakeNameResolver resolver;
ManagedChannelImpl managedChannel;
SynchronizationContext syncContext;
@Nullable
@Override
public NameResolver newNameResolver(URI targetUri, NameResolver.Args args) {
syncContext = args.getSynchronizationContext();
return (resolver = new FakeNameResolver(args));
}
@Override
public String getDefaultScheme() {
return "fake";
}
}
FakeNameResolverFactory2 factory = new FakeNameResolverFactory2();
ManagedChannelImplBuilder customBuilder = new ManagedChannelImplBuilder(TARGET,
new ClientTransportFactoryBuilder() {
@Override
public ClientTransportFactory buildClientTransportFactory() {
return mockTransportFactory;
}
},
null);
when(mockTransportFactory.getSupportedSocketAddressTypes()).thenReturn(Collections.singleton(
InetSocketAddress.class));
customBuilder.executorPool = executorPool;
customBuilder.channelz = channelz;
ManagedChannel mychannel = customBuilder.nameResolverFactory(factory).build();
ClientCall<Void, Void> call1 =
mychannel.newCall(TestMethodDescriptors.voidMethod(), CallOptions.DEFAULT);
ListenableFuture<Void> future1 = ClientCalls.futureUnaryCall(call1, null);
executor.runDueTasks();
try {
future1.get(1, TimeUnit.SECONDS);
Assert.fail();
} catch (ExecutionException e) {
assertThat(Throwables.getStackTraceAsString(e.getCause())).contains("kaboom");
}
// ok the service config is bad, let's fix it.
Map<String, Object> rawServiceConfig =
parseConfig("{\"loadBalancingConfig\": [{\"round_robin\": {}}]}");
Object fakeLbConfig = new Object();
PolicySelection lbConfigs =
new PolicySelection(
mockLoadBalancerProvider, fakeLbConfig);
mockLoadBalancerProvider.parseLoadBalancingPolicyConfig(rawServiceConfig);
ManagedChannelServiceConfig managedChannelServiceConfig =
createManagedChannelServiceConfig(rawServiceConfig, lbConfigs);
factory.syncContext.execute(() ->
factory.resolver.listener.onResult2(
ResolutionResult.newBuilder()
.setAddresses(addresses)
.setServiceConfig(ConfigOrError.fromConfig(managedChannelServiceConfig))
.build()));
ClientCall<Void, Void> call2 = mychannel.newCall(
TestMethodDescriptors.voidMethod(),
CallOptions.DEFAULT.withDeadlineAfter(5, TimeUnit.SECONDS));
ListenableFuture<Void> future2 = ClientCalls.futureUnaryCall(call2, null);
timer.forwardTime(1234, TimeUnit.SECONDS);
executor.runDueTasks();
try {
future2.get();
Assert.fail();
} catch (ExecutionException e) {
assertThat(Throwables.getStackTraceAsString(e.getCause())).contains("deadline");
}
mychannel.shutdownNow();
}
@Test
public void nameResolverArgsPropagation() {
final AtomicReference<NameResolver.Args> capturedArgs = new AtomicReference<>();
@ -4810,7 +4518,7 @@ public class ManagedChannelImplTest {
}
assertEquals(DEFAULT_PORT, args.getDefaultPort());
FakeNameResolverFactory.FakeNameResolver resolver =
new FakeNameResolverFactory.FakeNameResolver(targetUri, error, args);
new FakeNameResolverFactory.FakeNameResolver(targetUri, error);
resolvers.add(resolver);
return resolver;
}
@ -4838,16 +4546,14 @@ public class ManagedChannelImplTest {
final class FakeNameResolver extends NameResolver {
final URI targetUri;
final SynchronizationContext syncContext;
Listener2 listener;
boolean shutdown;
int refreshCalled;
Status error;
FakeNameResolver(URI targetUri, Status error, Args args) {
FakeNameResolver(URI targetUri, Status error) {
this.targetUri = targetUri;
this.error = error;
syncContext = args.getSynchronizationContext();
}
@Override public String getServiceAuthority() {
@ -4879,7 +4585,7 @@ public class ManagedChannelImplTest {
if (configOrError != null) {
builder.setServiceConfig(configOrError);
}
syncContext.execute(() -> listener.onResult(builder.build()));
listener.onResult(builder.build());
}
@Override public void shutdown() {

View File

@ -21,7 +21,6 @@ import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.isA;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import io.grpc.NameResolver;
import io.grpc.NameResolver.Listener2;
@ -80,7 +79,7 @@ public class RetryingNameResolverTest {
// Make sure the ResolutionResultListener callback is added to the ResolutionResult attributes,
// and the retry scheduler is reset since the name resolution was successful.
@Test
public void onResult_success() {
public void onResult_sucess() {
retryingNameResolver.start(mockListener);
verify(mockNameResolver).start(listenerCaptor.capture());
@ -95,18 +94,6 @@ public class RetryingNameResolverTest {
verify(mockRetryScheduler).reset();
}
@Test
public void onResult2_sucesss() {
when(mockListener.onResult2(isA(ResolutionResult.class))).thenReturn(Status.OK);
retryingNameResolver.start(mockListener);
verify(mockNameResolver).start(listenerCaptor.capture());
assertThat(listenerCaptor.getValue().onResult2(ResolutionResult.newBuilder().build()))
.isEqualTo(Status.OK);
verify(mockRetryScheduler).reset();
}
// Make sure the ResolutionResultListener callback is added to the ResolutionResult attributes,
// and that a retry gets scheduled when the resolution results are rejected.
@Test
@ -125,19 +112,6 @@ public class RetryingNameResolverTest {
verify(mockRetryScheduler).schedule(isA(Runnable.class));
}
// Make sure that a retry gets scheduled when the resolution results are rejected.
@Test
public void onResult2_failure() {
when(mockListener.onResult2(isA(ResolutionResult.class))).thenReturn(Status.UNAVAILABLE);
retryingNameResolver.start(mockListener);
verify(mockNameResolver).start(listenerCaptor.capture());
assertThat(listenerCaptor.getValue().onResult2(ResolutionResult.newBuilder().build()))
.isEqualTo(Status.UNAVAILABLE);
verify(mockRetryScheduler).schedule(isA(Runnable.class));
}
// Wrapping a NameResolver more than once is a misconfiguration.
@Test
public void onResult_failure_doubleWrapped() {

View File

@ -34,7 +34,7 @@ android {
protobuf {
protoc { artifact = 'com.google.protobuf:protoc:3.25.1' }
plugins {
grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.66.0-SNAPSHOT' // CURRENT_GRPC_VERSION
grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.66.0' // CURRENT_GRPC_VERSION
}
}
generateProtoTasks {
@ -54,12 +54,12 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.0.0'
// You need to build grpc-java to obtain these libraries below.
implementation 'io.grpc:grpc-okhttp:1.66.0-SNAPSHOT' // CURRENT_GRPC_VERSION
implementation 'io.grpc:grpc-protobuf-lite:1.66.0-SNAPSHOT' // CURRENT_GRPC_VERSION
implementation 'io.grpc:grpc-stub:1.66.0-SNAPSHOT' // CURRENT_GRPC_VERSION
implementation 'io.grpc:grpc-okhttp:1.66.0' // CURRENT_GRPC_VERSION
implementation 'io.grpc:grpc-protobuf-lite:1.66.0' // CURRENT_GRPC_VERSION
implementation 'io.grpc:grpc-stub:1.66.0' // CURRENT_GRPC_VERSION
implementation 'org.apache.tomcat:annotations-api:6.0.53'
testImplementation 'junit:junit:4.13.2'
testImplementation 'com.google.truth:truth:1.1.5'
testImplementation 'io.grpc:grpc-testing:1.66.0-SNAPSHOT' // CURRENT_GRPC_VERSION
testImplementation 'io.grpc:grpc-testing:1.66.0' // CURRENT_GRPC_VERSION
}

View File

@ -32,7 +32,7 @@ android {
protobuf {
protoc { artifact = 'com.google.protobuf:protoc:3.25.1' }
plugins {
grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.66.0-SNAPSHOT' // CURRENT_GRPC_VERSION
grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.66.0' // CURRENT_GRPC_VERSION
}
}
generateProtoTasks {
@ -52,8 +52,8 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.0.0'
// You need to build grpc-java to obtain these libraries below.
implementation 'io.grpc:grpc-okhttp:1.66.0-SNAPSHOT' // CURRENT_GRPC_VERSION
implementation 'io.grpc:grpc-protobuf-lite:1.66.0-SNAPSHOT' // CURRENT_GRPC_VERSION
implementation 'io.grpc:grpc-stub:1.66.0-SNAPSHOT' // CURRENT_GRPC_VERSION
implementation 'io.grpc:grpc-okhttp:1.66.0' // CURRENT_GRPC_VERSION
implementation 'io.grpc:grpc-protobuf-lite:1.66.0' // CURRENT_GRPC_VERSION
implementation 'io.grpc:grpc-stub:1.66.0' // CURRENT_GRPC_VERSION
implementation 'org.apache.tomcat:annotations-api:6.0.53'
}

View File

@ -32,7 +32,7 @@ android {
protobuf {
protoc { artifact = 'com.google.protobuf:protoc:3.25.1' }
plugins {
grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.66.0-SNAPSHOT' // CURRENT_GRPC_VERSION
grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.66.0' // CURRENT_GRPC_VERSION
}
}
generateProtoTasks {
@ -52,8 +52,8 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.0.0'
// You need to build grpc-java to obtain these libraries below.
implementation 'io.grpc:grpc-okhttp:1.66.0-SNAPSHOT' // CURRENT_GRPC_VERSION
implementation 'io.grpc:grpc-protobuf-lite:1.66.0-SNAPSHOT' // CURRENT_GRPC_VERSION
implementation 'io.grpc:grpc-stub:1.66.0-SNAPSHOT' // CURRENT_GRPC_VERSION
implementation 'io.grpc:grpc-okhttp:1.66.0' // CURRENT_GRPC_VERSION
implementation 'io.grpc:grpc-protobuf-lite:1.66.0' // CURRENT_GRPC_VERSION
implementation 'io.grpc:grpc-stub:1.66.0' // CURRENT_GRPC_VERSION
implementation 'org.apache.tomcat:annotations-api:6.0.53'
}

View File

@ -33,7 +33,7 @@ android {
protobuf {
protoc { artifact = 'com.google.protobuf:protoc:3.25.1' }
plugins {
grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.66.0-SNAPSHOT' // CURRENT_GRPC_VERSION
grpc { artifact = 'io.grpc:protoc-gen-grpc-java:1.66.0' // CURRENT_GRPC_VERSION
}
}
generateProtoTasks {
@ -53,8 +53,8 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.0.0'
// You need to build grpc-java to obtain these libraries below.
implementation 'io.grpc:grpc-okhttp:1.66.0-SNAPSHOT' // CURRENT_GRPC_VERSION
implementation 'io.grpc:grpc-protobuf-lite:1.66.0-SNAPSHOT' // CURRENT_GRPC_VERSION
implementation 'io.grpc:grpc-stub:1.66.0-SNAPSHOT' // CURRENT_GRPC_VERSION
implementation 'io.grpc:grpc-okhttp:1.66.0' // CURRENT_GRPC_VERSION
implementation 'io.grpc:grpc-protobuf-lite:1.66.0' // CURRENT_GRPC_VERSION
implementation 'io.grpc:grpc-stub:1.66.0' // CURRENT_GRPC_VERSION
implementation 'org.apache.tomcat:annotations-api:6.0.53'
}

View File

@ -23,7 +23,7 @@ java {
// 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.66.0-SNAPSHOT' // CURRENT_GRPC_VERSION
def grpcVersion = '1.66.0' // CURRENT_GRPC_VERSION
def protobufVersion = '3.25.3'
def protocVersion = protobufVersion

View File

@ -24,7 +24,7 @@ java {
// 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.66.0-SNAPSHOT' // CURRENT_GRPC_VERSION
def grpcVersion = '1.66.0' // CURRENT_GRPC_VERSION
def protocVersion = '3.25.3'
dependencies {

View File

@ -25,7 +25,7 @@ java {
// 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.66.0-SNAPSHOT' // CURRENT_GRPC_VERSION
def grpcVersion = '1.66.0' // CURRENT_GRPC_VERSION
def protobufVersion = '3.25.3'
dependencies {

View File

@ -6,13 +6,13 @@
<packaging>jar</packaging>
<!-- Feel free to delete the comment at the end of these lines. It is just
for safely updating the version in our release process. -->
<version>1.66.0-SNAPSHOT</version><!-- CURRENT_GRPC_VERSION -->
<version>1.66.0</version><!-- CURRENT_GRPC_VERSION -->
<name>example-debug</name>
<url>https://github.com/grpc/grpc-java</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<grpc.version>1.66.0-SNAPSHOT</grpc.version><!-- CURRENT_GRPC_VERSION -->
<grpc.version>1.66.0</grpc.version><!-- CURRENT_GRPC_VERSION -->
<protoc.version>3.25.3</protoc.version>
<!-- required for jdk9 -->
<maven.compiler.source>1.8</maven.compiler.source>

View File

@ -24,7 +24,7 @@ java {
// 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.66.0-SNAPSHOT' // CURRENT_GRPC_VERSION
def grpcVersion = '1.66.0' // CURRENT_GRPC_VERSION
def protobufVersion = '3.25.3'
def protocVersion = protobufVersion

View File

@ -6,13 +6,13 @@
<packaging>jar</packaging>
<!-- Feel free to delete the comment at the end of these lines. It is just
for safely updating the version in our release process. -->
<version>1.66.0-SNAPSHOT</version><!-- CURRENT_GRPC_VERSION -->
<version>1.66.0</version><!-- CURRENT_GRPC_VERSION -->
<name>example-gauth</name>
<url>https://github.com/grpc/grpc-java</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<grpc.version>1.66.0-SNAPSHOT</grpc.version><!-- CURRENT_GRPC_VERSION -->
<grpc.version>1.66.0</grpc.version><!-- CURRENT_GRPC_VERSION -->
<protobuf.version>3.25.3</protobuf.version>
<!-- required for jdk9 -->
<maven.compiler.source>1.8</maven.compiler.source>

View File

@ -25,7 +25,7 @@ java {
// 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.66.0-SNAPSHOT' // CURRENT_GRPC_VERSION
def grpcVersion = '1.66.0' // CURRENT_GRPC_VERSION
def protocVersion = '3.25.3'
def openTelemetryVersion = '1.40.0'
def openTelemetryPrometheusVersion = '1.40.0-alpha'

View File

@ -25,7 +25,7 @@ java {
// 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.66.0-SNAPSHOT' // CURRENT_GRPC_VERSION
def grpcVersion = '1.66.0' // CURRENT_GRPC_VERSION
def protocVersion = '3.25.3'
dependencies {

View File

@ -23,7 +23,7 @@ java {
// 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.66.0-SNAPSHOT' // CURRENT_GRPC_VERSION
def grpcVersion = '1.66.0' // CURRENT_GRPC_VERSION
def protobufVersion = '3.25.3'
dependencies {

View File

@ -6,13 +6,13 @@
<packaging>jar</packaging>
<!-- Feel free to delete the comment at the end of these lines. It is just
for safely updating the version in our release process. -->
<version>1.66.0-SNAPSHOT</version><!-- CURRENT_GRPC_VERSION -->
<version>1.66.0</version><!-- CURRENT_GRPC_VERSION -->
<name>example-hostname</name>
<url>https://github.com/grpc/grpc-java</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<grpc.version>1.66.0-SNAPSHOT</grpc.version><!-- CURRENT_GRPC_VERSION -->
<grpc.version>1.66.0</grpc.version><!-- CURRENT_GRPC_VERSION -->
<protoc.version>3.25.3</protoc.version>
<!-- required for jdk9 -->
<maven.compiler.source>1.8</maven.compiler.source>

View File

@ -23,7 +23,7 @@ java {
// 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.66.0-SNAPSHOT' // CURRENT_GRPC_VERSION
def grpcVersion = '1.66.0' // CURRENT_GRPC_VERSION
def protobufVersion = '3.25.3'
def protocVersion = protobufVersion

View File

@ -7,13 +7,13 @@
<packaging>jar</packaging>
<!-- Feel free to delete the comment at the end of these lines. It is just
for safely updating the version in our release process. -->
<version>1.66.0-SNAPSHOT</version><!-- CURRENT_GRPC_VERSION -->
<version>1.66.0</version><!-- CURRENT_GRPC_VERSION -->
<name>example-jwt-auth</name>
<url>https://github.com/grpc/grpc-java</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<grpc.version>1.66.0-SNAPSHOT</grpc.version><!-- CURRENT_GRPC_VERSION -->
<grpc.version>1.66.0</grpc.version><!-- CURRENT_GRPC_VERSION -->
<protobuf.version>3.25.3</protobuf.version>
<protoc.version>3.25.3</protoc.version>
<!-- required for jdk9 -->

View File

@ -23,7 +23,7 @@ java {
// 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.66.0-SNAPSHOT' // CURRENT_GRPC_VERSION
def grpcVersion = '1.66.0' // CURRENT_GRPC_VERSION
def protobufVersion = '3.25.3'
def protocVersion = protobufVersion

View File

@ -7,13 +7,13 @@
<packaging>jar</packaging>
<!-- Feel free to delete the comment at the end of these lines. It is just
for safely updating the version in our release process. -->
<version>1.66.0-SNAPSHOT</version><!-- CURRENT_GRPC_VERSION -->
<version>1.66.0</version><!-- CURRENT_GRPC_VERSION -->
<name>example-oauth</name>
<url>https://github.com/grpc/grpc-java</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<grpc.version>1.66.0-SNAPSHOT</grpc.version><!-- CURRENT_GRPC_VERSION -->
<grpc.version>1.66.0</grpc.version><!-- CURRENT_GRPC_VERSION -->
<protobuf.version>3.25.3</protobuf.version>
<protoc.version>3.25.3</protoc.version>
<!-- required for jdk9 -->

View File

@ -24,7 +24,7 @@ java {
// 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.66.0-SNAPSHOT' // CURRENT_GRPC_VERSION
def grpcVersion = '1.66.0' // CURRENT_GRPC_VERSION
def protocVersion = '3.25.3'
def openTelemetryVersion = '1.40.0'
def openTelemetryPrometheusVersion = '1.40.0-alpha'

View File

@ -18,7 +18,7 @@ java {
targetCompatibility = JavaVersion.VERSION_1_8
}
def grpcVersion = '1.66.0-SNAPSHOT' // CURRENT_GRPC_VERSION
def grpcVersion = '1.66.0' // CURRENT_GRPC_VERSION
def protocVersion = '3.25.3'
dependencies {

View File

@ -18,7 +18,7 @@ java {
targetCompatibility = JavaVersion.VERSION_1_8
}
def grpcVersion = '1.66.0-SNAPSHOT' // CURRENT_GRPC_VERSION
def grpcVersion = '1.66.0' // CURRENT_GRPC_VERSION
def protocVersion = '3.25.3'
dependencies {

View File

@ -16,7 +16,7 @@ java {
targetCompatibility = JavaVersion.VERSION_1_8
}
def grpcVersion = '1.66.0-SNAPSHOT' // CURRENT_GRPC_VERSION
def grpcVersion = '1.66.0' // CURRENT_GRPC_VERSION
def protocVersion = '3.25.3'
dependencies {

View File

@ -24,7 +24,7 @@ java {
// 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.66.0-SNAPSHOT' // CURRENT_GRPC_VERSION
def grpcVersion = '1.66.0' // CURRENT_GRPC_VERSION
def protocVersion = '3.25.3'
dependencies {

View File

@ -6,13 +6,13 @@
<packaging>jar</packaging>
<!-- Feel free to delete the comment at the end of these lines. It is just
for safely updating the version in our release process. -->
<version>1.66.0-SNAPSHOT</version><!-- CURRENT_GRPC_VERSION -->
<version>1.66.0</version><!-- CURRENT_GRPC_VERSION -->
<name>example-tls</name>
<url>https://github.com/grpc/grpc-java</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<grpc.version>1.66.0-SNAPSHOT</grpc.version><!-- CURRENT_GRPC_VERSION -->
<grpc.version>1.66.0</grpc.version><!-- CURRENT_GRPC_VERSION -->
<protoc.version>3.25.3</protoc.version>
<!-- required for jdk9 -->
<maven.compiler.source>1.8</maven.compiler.source>

View File

@ -23,7 +23,7 @@ java {
// 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.66.0-SNAPSHOT' // CURRENT_GRPC_VERSION
def grpcVersion = '1.66.0' // CURRENT_GRPC_VERSION
def protocVersion = '3.25.3'
dependencies {

View File

@ -6,13 +6,13 @@
<packaging>jar</packaging>
<!-- Feel free to delete the comment at the end of these lines. It is just
for safely updating the version in our release process. -->
<version>1.66.0-SNAPSHOT</version><!-- CURRENT_GRPC_VERSION -->
<version>1.66.0</version><!-- CURRENT_GRPC_VERSION -->
<name>examples</name>
<url>https://github.com/grpc/grpc-java</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<grpc.version>1.66.0-SNAPSHOT</grpc.version><!-- CURRENT_GRPC_VERSION -->
<grpc.version>1.66.0</grpc.version><!-- CURRENT_GRPC_VERSION -->
<protobuf.version>3.25.3</protobuf.version>
<protoc.version>3.25.3</protoc.version>
<!-- required for JDK 8 -->

View File

@ -152,7 +152,7 @@ public class GrpclbNameResolverTest {
resolver.start(mockListener);
assertThat(fakeClock.runDueTasks()).isEqualTo(1);
verify(mockListener).onResult2(resultCaptor.capture());
verify(mockListener).onResult(resultCaptor.capture());
ResolutionResult result = resultCaptor.getValue();
assertThat(result.getAddresses()).isEmpty();
assertThat(result.getAttributes()).isEqualTo(Attributes.EMPTY);
@ -192,7 +192,7 @@ public class GrpclbNameResolverTest {
resolver.start(mockListener);
assertThat(fakeClock.runDueTasks()).isEqualTo(1);
verify(mockListener).onResult2(resultCaptor.capture());
verify(mockListener).onResult(resultCaptor.capture());
ResolutionResult result = resultCaptor.getValue();
InetSocketAddress resolvedBackendAddr =
(InetSocketAddress) Iterables.getOnlyElement(
@ -225,7 +225,7 @@ public class GrpclbNameResolverTest {
resolver.start(mockListener);
assertThat(fakeClock.runDueTasks()).isEqualTo(1);
verify(mockListener).onResult2(resultCaptor.capture());
verify(mockListener).onResult(resultCaptor.capture());
ResolutionResult result = resultCaptor.getValue();
assertThat(result.getAddresses())
.containsExactly(
@ -272,7 +272,7 @@ public class GrpclbNameResolverTest {
resolver.start(mockListener);
assertThat(fakeClock.runDueTasks()).isEqualTo(1);
verify(mockListener).onResult2(resultCaptor.capture());
verify(mockListener).onResult(resultCaptor.capture());
ResolutionResult result = resultCaptor.getValue();
assertThat(result.getAddresses()).isEmpty();
EquivalentAddressGroup resolvedBalancerAddr =
@ -306,7 +306,7 @@ public class GrpclbNameResolverTest {
resolver.start(mockListener);
assertThat(fakeClock.runDueTasks()).isEqualTo(1);
verify(mockListener).onResult2(resultCaptor.capture());
verify(mockListener).onResult(resultCaptor.capture());
ResolutionResult result = resultCaptor.getValue();
InetSocketAddress resolvedBackendAddr =

View File

@ -152,8 +152,14 @@ final class ControlPlaneClient {
startRpcStream();
}
Collection<String> resources = resourceStore.getSubscribedResources(serverInfo, resourceType);
if (resources != null) {
if (resources == null) {
resources = Collections.emptyList();
}
adsStream.sendDiscoveryRequest(resourceType, resources);
if (resources.isEmpty()) {
// The resource type no longer has subscribing resources; clean up references to it
versions.remove(resourceType);
adsStream.respNonces.remove(resourceType);
}
}

View File

@ -281,7 +281,7 @@ public final class XdsClientImpl extends XdsClient implements XdsResponseHandler
@SuppressWarnings("unchecked")
public void run() {
ResourceSubscriber<T> subscriber =
(ResourceSubscriber<T>) resourceSubscribers.get(type).get(resourceName);;
(ResourceSubscriber<T>) resourceSubscribers.get(type).get(resourceName);
subscriber.removeWatcher(watcher);
if (!subscriber.isWatched()) {
subscriber.cancelResourceWatch();

View File

@ -133,6 +133,7 @@ import org.mockito.invocation.InvocationOnMock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.mockito.stubbing.Answer;
import org.mockito.verification.VerificationMode;
/**
* Tests for {@link XdsClientImpl}.
@ -2757,6 +2758,37 @@ public abstract class GrpcXdsClientImplTestBase {
verifySubscribedResourcesMetadataSizes(0, 0, 0, 1);
}
@Test
public void edsCleanupNonceAfterUnsubscription() {
Assume.assumeFalse(ignoreResourceDeletion());
// Suppose we have an EDS subscription A.1
xdsClient.watchXdsResource(XdsEndpointResource.getInstance(), "A.1", edsResourceWatcher);
DiscoveryRpcCall call = resourceDiscoveryCalls.poll();
assertThat(call).isNotNull();
call.verifyRequest(EDS, "A.1", "", "", NODE);
// EDS -> {A.1}, version 1
List<Message> dropOverloads = ImmutableList.of();
List<Message> endpointsV1 = ImmutableList.of(lbEndpointHealthy);
ImmutableMap<String, Any> resourcesV1 = ImmutableMap.of(
"A.1", Any.pack(mf.buildClusterLoadAssignment("A.1", endpointsV1, dropOverloads)));
call.sendResponse(EDS, resourcesV1.values().asList(), VERSION_1, "0000");
// {A.1} -> ACK, version 1
call.verifyRequest(EDS, "A.1", VERSION_1, "0000", NODE);
verify(edsResourceWatcher, times(1)).onChanged(any());
// trigger an EDS resource unsubscription.
xdsClient.cancelXdsResourceWatch(XdsEndpointResource.getInstance(), "A.1", edsResourceWatcher);
verifySubscribedResourcesMetadataSizes(0, 0, 0, 0);
call.verifyRequest(EDS, Arrays.asList(), VERSION_1, "0000", NODE);
// When re-subscribing, the version and nonce were properly forgotten, so the request is the
// same as the initial request
xdsClient.watchXdsResource(XdsEndpointResource.getInstance(), "A.1", edsResourceWatcher);
call.verifyRequest(EDS, "A.1", "", "", NODE, Mockito.timeout(2000).times(2));
}
@Test
public void edsResponseErrorHandling_allResourcesFailedUnpack() {
DiscoveryRpcCall call = startResourceWatcher(XdsEndpointResource.getInstance(), EDS_RESOURCE,
@ -3787,10 +3819,22 @@ public abstract class GrpcXdsClientImplTestBase {
protected void verifyRequest(
XdsResourceType<?> type, List<String> resources, String versionInfo, String nonce,
Node node) {
Node node, VerificationMode verificationMode) {
throw new UnsupportedOperationException();
}
protected void verifyRequest(
XdsResourceType<?> type, List<String> resources, String versionInfo, String nonce,
Node node) {
verifyRequest(type, resources, versionInfo, nonce, node, Mockito.timeout(2000));
}
protected void verifyRequest(
XdsResourceType<?> type, String resource, String versionInfo, String nonce,
Node node, VerificationMode verificationMode) {
verifyRequest(type, ImmutableList.of(resource), versionInfo, nonce, node, verificationMode);
}
protected void verifyRequest(
XdsResourceType<?> type, String resource, String versionInfo, String nonce, Node node) {
verifyRequest(type, ImmutableList.of(resource), versionInfo, nonce, node);

View File

@ -118,6 +118,7 @@ import org.junit.runners.Parameterized.Parameters;
import org.mockito.ArgumentMatcher;
import org.mockito.InOrder;
import org.mockito.Mockito;
import org.mockito.verification.VerificationMode;
/**
* Tests for {@link XdsClientImpl} with protocol version v3.
@ -205,8 +206,8 @@ public class GrpcXdsClientImplV3Test extends GrpcXdsClientImplTestBase {
@Override
protected void verifyRequest(
XdsResourceType<?> type, List<String> resources, String versionInfo, String nonce,
EnvoyProtoData.Node node) {
verify(requestObserver, Mockito.timeout(2000)).onNext(argThat(new DiscoveryRequestMatcher(
EnvoyProtoData.Node node, VerificationMode verificationMode) {
verify(requestObserver, verificationMode).onNext(argThat(new DiscoveryRequestMatcher(
node.toEnvoyProtoNode(), versionInfo, resources, type.typeUrl(), nonce, null, null)));
}