core: Remove RetryingNR.RESOLUTION_RESULT_LISTENER_KEY It was introduced in fcb5c54e4 because at the time we didn't change the API to communicate the status. When onResult2() was introduced in 90d0fabb1 this hack stopped being necessary.
diff --git a/core/src/main/java/io/grpc/internal/ManagedChannelImpl.java b/core/src/main/java/io/grpc/internal/ManagedChannelImpl.java index 976587a..9b756c3 100644 --- a/core/src/main/java/io/grpc/internal/ManagedChannelImpl.java +++ b/core/src/main/java/io/grpc/internal/ManagedChannelImpl.java
@@ -94,7 +94,6 @@ import io.grpc.internal.ManagedChannelServiceConfig.ServiceConfigConvertedSelector; import io.grpc.internal.RetriableStream.ChannelBufferMeter; import io.grpc.internal.RetriableStream.Throttle; -import io.grpc.internal.RetryingNameResolver.ResolutionResultListener; import java.net.URI; import java.util.ArrayList; import java.util.Collection; @@ -1653,18 +1652,7 @@ @Override 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()); + syncContext.execute(() -> onResult2(resolutionResult)); } @SuppressWarnings("ReferenceEquality")
diff --git a/core/src/main/java/io/grpc/internal/RetryingNameResolver.java b/core/src/main/java/io/grpc/internal/RetryingNameResolver.java index 6dcfcd3..55fedea 100644 --- a/core/src/main/java/io/grpc/internal/RetryingNameResolver.java +++ b/core/src/main/java/io/grpc/internal/RetryingNameResolver.java
@@ -17,7 +17,6 @@ package io.grpc.internal; import com.google.common.annotations.VisibleForTesting; -import io.grpc.Attributes; import io.grpc.NameResolver; import io.grpc.Status; import io.grpc.SynchronizationContext; @@ -34,9 +33,6 @@ private final RetryScheduler retryScheduler; private final SynchronizationContext syncContext; - static final Attributes.Key<ResolutionResultListener> RESOLUTION_RESULT_LISTENER_KEY - = Attributes.Key.create( - "io.grpc.internal.RetryingNameResolver.RESOLUTION_RESULT_LISTENER_KEY"); /** * Creates a new {@link RetryingNameResolver}. @@ -88,18 +84,7 @@ @Override public void onResult(ResolutionResult resolutionResult) { - // If the resolution result listener is already an attribute it indicates that a name resolver - // has already been wrapped with this class. This indicates a misconfiguration. - if (resolutionResult.getAttributes().get(RESOLUTION_RESULT_LISTENER_KEY) != null) { - throw new IllegalStateException( - "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()); + syncContext.execute(() -> onResult2(resolutionResult)); } @Override @@ -119,19 +104,4 @@ syncContext.execute(() -> retryScheduler.schedule(new DelayedNameResolverRefresh())); } } - - /** - * Simple callback class to store in {@link ResolutionResult} attributes so that - * ManagedChannel can indicate if the resolved addresses were accepted. Temporary until - * the Listener2.onResult() API can be changed to return a boolean for this purpose. - */ - class ResolutionResultListener { - public void resolutionAttempted(Status successStatus) { - if (successStatus.isOk()) { - retryScheduler.reset(); - } else { - retryScheduler.schedule(new DelayedNameResolverRefresh()); - } - } - } }
diff --git a/core/src/test/java/io/grpc/internal/ManagedChannelImplTest.java b/core/src/test/java/io/grpc/internal/ManagedChannelImplTest.java index ac84594..6dfba74 100644 --- a/core/src/test/java/io/grpc/internal/ManagedChannelImplTest.java +++ b/core/src/test/java/io/grpc/internal/ManagedChannelImplTest.java
@@ -3844,8 +3844,6 @@ verify(mockLoadBalancer).acceptResolvedAddresses(resolvedAddressCaptor.capture()); ResolvedAddresses resolvedAddresses = resolvedAddressCaptor.getValue(); assertThat(resolvedAddresses.getAddresses()).isEqualTo(nameResolverFactory.servers); - assertThat(resolvedAddresses.getAttributes() - .get(RetryingNameResolver.RESOLUTION_RESULT_LISTENER_KEY)).isNotNull(); // simulating request connection and then transport ready after resolved address Subchannel subchannel = @@ -3951,8 +3949,6 @@ verify(mockLoadBalancer).acceptResolvedAddresses(resolvedAddressCaptor.capture()); ResolvedAddresses resolvedAddresses = resolvedAddressCaptor.getValue(); assertThat(resolvedAddresses.getAddresses()).isEqualTo(nameResolverFactory.servers); - assertThat(resolvedAddresses.getAttributes() - .get(RetryingNameResolver.RESOLUTION_RESULT_LISTENER_KEY)).isNotNull(); // simulating request connection and then transport ready after resolved address Subchannel subchannel =
diff --git a/core/src/test/java/io/grpc/internal/RetryingNameResolverTest.java b/core/src/test/java/io/grpc/internal/RetryingNameResolverTest.java index 6347416..1da93f0 100644 --- a/core/src/test/java/io/grpc/internal/RetryingNameResolverTest.java +++ b/core/src/test/java/io/grpc/internal/RetryingNameResolverTest.java
@@ -17,7 +17,6 @@ package io.grpc.internal; import static com.google.common.truth.Truth.assertThat; -import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.isA; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -28,7 +27,6 @@ import io.grpc.NameResolver.ResolutionResult; import io.grpc.Status; import io.grpc.SynchronizationContext; -import io.grpc.internal.RetryingNameResolver.ResolutionResultListener; import java.lang.Thread.UncaughtExceptionHandler; import org.junit.Before; import org.junit.Rule; @@ -58,8 +56,6 @@ private RetryScheduler mockRetryScheduler; @Captor private ArgumentCaptor<Listener2> listenerCaptor; - @Captor - private ArgumentCaptor<ResolutionResult> onResultCaptor; private final SynchronizationContext syncContext = new SynchronizationContext( mock(UncaughtExceptionHandler.class)); @@ -77,21 +73,14 @@ retryingNameResolver.shutdown(); } - // 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() { + when(mockListener.onResult2(isA(ResolutionResult.class))).thenReturn(Status.OK); retryingNameResolver.start(mockListener); verify(mockNameResolver).start(listenerCaptor.capture()); listenerCaptor.getValue().onResult(ResolutionResult.newBuilder().build()); - verify(mockListener).onResult(onResultCaptor.capture()); - ResolutionResultListener resolutionResultListener = onResultCaptor.getValue() - .getAttributes() - .get(RetryingNameResolver.RESOLUTION_RESULT_LISTENER_KEY); - assertThat(resolutionResultListener).isNotNull(); - resolutionResultListener.resolutionAttempted(Status.OK); verify(mockRetryScheduler).reset(); } @@ -107,21 +96,15 @@ 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. + // Make sure that a retry gets scheduled when the resolution results are rejected. @Test public void onResult_failure() { + when(mockListener.onResult2(isA(ResolutionResult.class))).thenReturn(Status.UNAVAILABLE); retryingNameResolver.start(mockListener); verify(mockNameResolver).start(listenerCaptor.capture()); listenerCaptor.getValue().onResult(ResolutionResult.newBuilder().build()); - verify(mockListener).onResult(onResultCaptor.capture()); - ResolutionResultListener resolutionResultListener = onResultCaptor.getValue() - .getAttributes() - .get(RetryingNameResolver.RESOLUTION_RESULT_LISTENER_KEY); - assertThat(resolutionResultListener).isNotNull(); - resolutionResultListener.resolutionAttempted(Status.UNAVAILABLE); verify(mockRetryScheduler).schedule(isA(Runnable.class)); } @@ -138,24 +121,6 @@ verify(mockRetryScheduler).schedule(isA(Runnable.class)); } - // Wrapping a NameResolver more than once is a misconfiguration. - @Test - public void onResult_failure_doubleWrapped() { - NameResolver doubleWrappedResolver = new RetryingNameResolver(retryingNameResolver, - mockRetryScheduler, syncContext); - - doubleWrappedResolver.start(mockListener); - verify(mockNameResolver).start(listenerCaptor.capture()); - - try { - listenerCaptor.getValue().onResult(ResolutionResult.newBuilder().build()); - } catch (IllegalStateException e) { - assertThat(e).hasMessageThat().contains("can only be used once"); - return; - } - fail("An exception should have been thrown for a double wrapped NAmeResolver"); - } - // A retry should get scheduled when name resolution fails. @Test public void onError() { @@ -165,4 +130,4 @@ verify(mockListener).onError(Status.DEADLINE_EXCEEDED); verify(mockRetryScheduler).schedule(isA(Runnable.class)); } -} \ No newline at end of file +}