diff --git a/api/src/main/java/io/grpc/LoadBalancer.java b/api/src/main/java/io/grpc/LoadBalancer.java
index 3cef6190087..6469e33b907 100644
--- a/api/src/main/java/io/grpc/LoadBalancer.java
+++ b/api/src/main/java/io/grpc/LoadBalancer.java
@@ -124,39 +124,46 @@ public abstract class LoadBalancer {
*
*
Implementations should not modify the given {@code servers}.
*
- * @param servers the resolved server addresses, never empty.
- * @param attributes extra information from naming system.
- * @deprecated override {@link #handleResolvedAddresses(ResolvedAddresses) instead}
- * @since 1.2.0
+ * @param resolvedAddresses the resolved server addresses, attributes, and config.
+ * @since 1.21.0
*/
- @Deprecated
- public void handleResolvedAddressGroups(
- List servers,
- @NameResolver.ResolutionResultAttr Attributes attributes) {
+ public void handleResolvedAddresses(ResolvedAddresses resolvedAddresses) {
if (recursionCount++ == 0) {
- handleResolvedAddresses(
- ResolvedAddresses.newBuilder().setAddresses(servers).setAttributes(attributes).build());
+ // Note that the information about the addresses actually being accepted will be lost
+ // if you rely on this method for backward compatibility.
+ acceptResolvedAddresses(resolvedAddresses);
}
recursionCount = 0;
}
/**
- * Handles newly resolved server groups and metadata attributes from name resolution system.
- * {@code servers} contained in {@link EquivalentAddressGroup} should be considered equivalent
- * but may be flattened into a single list if needed.
+ * Accepts newly resolved addresses from the name resolution system. The {@link
+ * EquivalentAddressGroup} addresses should be considered equivalent but may be flattened into a
+ * single list if needed.
*
- * Implementations should not modify the given {@code servers}.
+ *
Implementations can choose to reject the given addresses by returning {@code false}.
+ *
+ *
Implementations should not modify the given {@code addresses}.
*
* @param resolvedAddresses the resolved server addresses, attributes, and config.
- * @since 1.21.0
+ * @return {@code true} if the resolved addresses were accepted. {@code false} if rejected.
+ * @since 1.49.0
*/
- @SuppressWarnings("deprecation")
- public void handleResolvedAddresses(ResolvedAddresses resolvedAddresses) {
- if (recursionCount++ == 0) {
- handleResolvedAddressGroups(
- resolvedAddresses.getAddresses(), resolvedAddresses.getAttributes());
+ public boolean acceptResolvedAddresses(ResolvedAddresses resolvedAddresses) {
+ if (resolvedAddresses.getAddresses().isEmpty()
+ && !canHandleEmptyAddressListFromNameResolution()) {
+ handleNameResolutionError(Status.UNAVAILABLE.withDescription(
+ "NameResolver returned no usable address. addrs=" + resolvedAddresses.getAddresses()
+ + ", attrs=" + resolvedAddresses.getAttributes()));
+ return false;
+ } else {
+ if (recursionCount++ == 0) {
+ handleResolvedAddresses(resolvedAddresses);
+ }
+ recursionCount = 0;
+
+ return true;
}
- recursionCount = 0;
}
/**
diff --git a/api/src/test/java/io/grpc/LoadBalancerTest.java b/api/src/test/java/io/grpc/LoadBalancerTest.java
index be3d10ba2ae..beaf3335e2c 100644
--- a/api/src/test/java/io/grpc/LoadBalancerTest.java
+++ b/api/src/test/java/io/grpc/LoadBalancerTest.java
@@ -235,13 +235,14 @@ public void createSubchannelArgs_toString() {
@Deprecated
@Test
- public void handleResolvedAddressGroups_delegatesToHandleResolvedAddresses() {
+ public void handleResolvedAddresses_delegatesToAcceptResolvedAddresses() {
final AtomicReference resultCapture = new AtomicReference<>();
LoadBalancer balancer = new LoadBalancer() {
@Override
- public void handleResolvedAddresses(ResolvedAddresses resolvedAddresses) {
+ public boolean acceptResolvedAddresses(ResolvedAddresses resolvedAddresses) {
resultCapture.set(resolvedAddresses);
+ return true;
}
@Override
@@ -260,23 +261,22 @@ public void shutdown() {
List servers = Arrays.asList(
new EquivalentAddressGroup(new SocketAddress(){}),
new EquivalentAddressGroup(new SocketAddress(){}));
- balancer.handleResolvedAddressGroups(servers, attrs);
+ ResolvedAddresses addresses = ResolvedAddresses.newBuilder().setAddresses(servers)
+ .setAttributes(attrs).build();
+ balancer.handleResolvedAddresses(addresses);
assertThat(resultCapture.get()).isEqualTo(
ResolvedAddresses.newBuilder().setAddresses(servers).setAttributes(attrs).build());
}
@Deprecated
@Test
- public void handleResolvedAddresses_delegatesToHandleResolvedAddressGroups() {
- final AtomicReference> serversCapture = new AtomicReference<>();
- final AtomicReference attrsCapture = new AtomicReference<>();
+ public void acceptResolvedAddresses_delegatesToHandleResolvedAddressGroups() {
+ final AtomicReference addressesCapture = new AtomicReference<>();
LoadBalancer balancer = new LoadBalancer() {
@Override
- public void handleResolvedAddressGroups(
- List servers, Attributes attrs) {
- serversCapture.set(servers);
- attrsCapture.set(attrs);
+ public void handleResolvedAddresses(ResolvedAddresses addresses) {
+ addressesCapture.set(addresses);
}
@Override
@@ -295,25 +295,23 @@ public void shutdown() {
List servers = Arrays.asList(
new EquivalentAddressGroup(new SocketAddress(){}),
new EquivalentAddressGroup(new SocketAddress(){}));
- balancer.handleResolvedAddresses(
- ResolvedAddresses.newBuilder().setAddresses(servers).setAttributes(attrs).build());
- assertThat(serversCapture.get()).isEqualTo(servers);
- assertThat(attrsCapture.get()).isEqualTo(attrs);
+ ResolvedAddresses addresses = ResolvedAddresses.newBuilder().setAddresses(servers)
+ .setAttributes(attrs).build();
+ balancer.handleResolvedAddresses(addresses);
+ assertThat(addressesCapture.get().getAddresses()).isEqualTo(servers);
+ assertThat(addressesCapture.get().getAttributes()).isEqualTo(attrs);
}
@Deprecated
@Test
- public void handleResolvedAddresses_noInfiniteLoop() {
- final List> serversCapture = new ArrayList<>();
- final List attrsCapture = new ArrayList<>();
+ public void acceptResolvedAddresses_noInfiniteLoop() {
+ final List addressesCapture = new ArrayList<>();
LoadBalancer balancer = new LoadBalancer() {
@Override
- public void handleResolvedAddressGroups(
- List servers, Attributes attrs) {
- serversCapture.add(servers);
- attrsCapture.add(attrs);
- super.handleResolvedAddressGroups(servers, attrs);
+ public void handleResolvedAddresses(ResolvedAddresses addresses) {
+ addressesCapture.add(addresses);
+ super.handleResolvedAddresses(addresses);
}
@Override
@@ -328,12 +326,12 @@ public void shutdown() {
List servers = Arrays.asList(
new EquivalentAddressGroup(new SocketAddress(){}),
new EquivalentAddressGroup(new SocketAddress(){}));
- balancer.handleResolvedAddresses(
- ResolvedAddresses.newBuilder().setAddresses(servers).setAttributes(attrs).build());
- assertThat(serversCapture).hasSize(1);
- assertThat(attrsCapture).hasSize(1);
- assertThat(serversCapture.get(0)).isEqualTo(servers);
- assertThat(attrsCapture.get(0)).isEqualTo(attrs);
+ ResolvedAddresses addresses = ResolvedAddresses.newBuilder().setAddresses(servers)
+ .setAttributes(attrs).build();
+ balancer.handleResolvedAddresses(addresses);
+ assertThat(addressesCapture).hasSize(1);
+ assertThat(addressesCapture.get(0).getAddresses()).isEqualTo(servers);
+ assertThat(addressesCapture.get(0).getAttributes()).isEqualTo(attrs);
}
private static class NoopHelper extends LoadBalancer.Helper {
diff --git a/core/src/main/java/io/grpc/internal/AutoConfiguredLoadBalancerFactory.java b/core/src/main/java/io/grpc/internal/AutoConfiguredLoadBalancerFactory.java
index 01c48b9efcf..b8c9cab7459 100644
--- a/core/src/main/java/io/grpc/internal/AutoConfiguredLoadBalancerFactory.java
+++ b/core/src/main/java/io/grpc/internal/AutoConfiguredLoadBalancerFactory.java
@@ -20,11 +20,9 @@
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.MoreObjects;
-import io.grpc.Attributes;
import io.grpc.ChannelLogger.ChannelLogLevel;
import io.grpc.ConnectivityState;
import io.grpc.ConnectivityStateInfo;
-import io.grpc.EquivalentAddressGroup;
import io.grpc.LoadBalancer;
import io.grpc.LoadBalancer.Helper;
import io.grpc.LoadBalancer.PickResult;
@@ -67,10 +65,14 @@ private static final class NoopLoadBalancer extends LoadBalancer {
@Override
@Deprecated
- public void handleResolvedAddressGroups(List s, Attributes a) {}
+ @SuppressWarnings("InlineMeSuggester")
+ public void handleResolvedAddresses(ResolvedAddresses resolvedAddresses) {
+ }
@Override
- public void handleResolvedAddresses(ResolvedAddresses resolvedAddresses) {}
+ public boolean acceptResolvedAddresses(ResolvedAddresses resolvedAddresses) {
+ return true;
+ }
@Override
public void handleNameResolutionError(Status error) {}
@@ -97,14 +99,10 @@ public final class AutoConfiguredLoadBalancer {
}
/**
- * Returns non-OK status if resolvedAddresses is empty and delegate lb requires address ({@link
- * LoadBalancer#canHandleEmptyAddressListFromNameResolution()} returns {@code false}). {@code
- * AutoConfiguredLoadBalancer} doesn't expose {@code
- * canHandleEmptyAddressListFromNameResolution} because it depends on the delegated LB.
+ * Returns non-OK status if the delegate rejects the resolvedAddresses (e.g. if it does not
+ * support an empty list).
*/
- Status tryHandleResolvedAddresses(ResolvedAddresses resolvedAddresses) {
- List servers = resolvedAddresses.getAddresses();
- Attributes attributes = resolvedAddresses.getAttributes();
+ boolean tryAcceptResolvedAddresses(ResolvedAddresses resolvedAddresses) {
PolicySelection policySelection =
(PolicySelection) resolvedAddresses.getLoadBalancingPolicyConfig();
@@ -118,7 +116,7 @@ Status tryHandleResolvedAddresses(ResolvedAddresses resolvedAddresses) {
delegate.shutdown();
delegateProvider = null;
delegate = new NoopLoadBalancer();
- return Status.OK;
+ return true;
}
policySelection =
new PolicySelection(defaultProvider, /* config= */ null);
@@ -141,20 +139,12 @@ Status tryHandleResolvedAddresses(ResolvedAddresses resolvedAddresses) {
ChannelLogLevel.DEBUG, "Load-balancing config: {0}", policySelection.config);
}
- LoadBalancer delegate = getDelegate();
- if (resolvedAddresses.getAddresses().isEmpty()
- && !delegate.canHandleEmptyAddressListFromNameResolution()) {
- return Status.UNAVAILABLE.withDescription(
- "NameResolver returned no usable address. addrs=" + servers + ", attrs=" + attributes);
- } else {
- delegate.handleResolvedAddresses(
- ResolvedAddresses.newBuilder()
- .setAddresses(resolvedAddresses.getAddresses())
- .setAttributes(attributes)
- .setLoadBalancingPolicyConfig(lbConfig)
- .build());
- return Status.OK;
- }
+ return getDelegate().acceptResolvedAddresses(
+ ResolvedAddresses.newBuilder()
+ .setAddresses(resolvedAddresses.getAddresses())
+ .setAttributes(resolvedAddresses.getAttributes())
+ .setLoadBalancingPolicyConfig(lbConfig)
+ .build());
}
void handleNameResolutionError(Status error) {
diff --git a/core/src/main/java/io/grpc/internal/ManagedChannelImpl.java b/core/src/main/java/io/grpc/internal/ManagedChannelImpl.java
index f7b82d1db17..6e80eb39255 100644
--- a/core/src/main/java/io/grpc/internal/ManagedChannelImpl.java
+++ b/core/src/main/java/io/grpc/internal/ManagedChannelImpl.java
@@ -1852,16 +1852,17 @@ public void run() {
.set(LoadBalancer.ATTR_HEALTH_CHECKING_CONFIG, healthCheckingConfig)
.build();
}
+ Attributes attributes = attrBuilder.build();
- Status handleResult = helper.lb.tryHandleResolvedAddresses(
+ boolean addressesAccepted = helper.lb.tryAcceptResolvedAddresses(
ResolvedAddresses.newBuilder()
.setAddresses(servers)
- .setAttributes(attrBuilder.build())
+ .setAttributes(attributes)
.setLoadBalancingPolicyConfig(effectiveServiceConfig.getLoadBalancingConfig())
.build());
- if (!handleResult.isOk()) {
- handleErrorInSyncContext(handleResult.augmentDescription(resolver + " was used"));
+ if (!addressesAccepted) {
+ scheduleExponentialBackOffInSyncContext();
}
}
}
diff --git a/core/src/main/java/io/grpc/util/ForwardingLoadBalancer.java b/core/src/main/java/io/grpc/util/ForwardingLoadBalancer.java
index 628eda3b71b..516488f0d1a 100644
--- a/core/src/main/java/io/grpc/util/ForwardingLoadBalancer.java
+++ b/core/src/main/java/io/grpc/util/ForwardingLoadBalancer.java
@@ -17,14 +17,10 @@
package io.grpc.util;
import com.google.common.base.MoreObjects;
-import io.grpc.Attributes;
import io.grpc.ConnectivityStateInfo;
-import io.grpc.EquivalentAddressGroup;
import io.grpc.ExperimentalApi;
import io.grpc.LoadBalancer;
-import io.grpc.NameResolver;
import io.grpc.Status;
-import java.util.List;
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
public abstract class ForwardingLoadBalancer extends LoadBalancer {
@@ -34,16 +30,13 @@ public abstract class ForwardingLoadBalancer extends LoadBalancer {
protected abstract LoadBalancer delegate();
@Override
- @Deprecated
- public void handleResolvedAddressGroups(
- List servers,
- @NameResolver.ResolutionResultAttr Attributes attributes) {
- delegate().handleResolvedAddressGroups(servers, attributes);
+ public void handleResolvedAddresses(ResolvedAddresses resolvedAddresses) {
+ delegate().handleResolvedAddresses(resolvedAddresses);
}
@Override
- public void handleResolvedAddresses(ResolvedAddresses resolvedAddresses) {
- delegate().handleResolvedAddresses(resolvedAddresses);
+ public boolean acceptResolvedAddresses(ResolvedAddresses resolvedAddresses) {
+ return delegate().acceptResolvedAddresses(resolvedAddresses);
}
@Override
diff --git a/core/src/test/java/io/grpc/internal/AutoConfiguredLoadBalancerFactoryTest.java b/core/src/test/java/io/grpc/internal/AutoConfiguredLoadBalancerFactoryTest.java
index bf7c63818cf..ad886c31142 100644
--- a/core/src/test/java/io/grpc/internal/AutoConfiguredLoadBalancerFactoryTest.java
+++ b/core/src/test/java/io/grpc/internal/AutoConfiguredLoadBalancerFactoryTest.java
@@ -21,8 +21,8 @@
import static org.mockito.AdditionalAnswers.delegatesTo;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isA;
import static org.mockito.ArgumentMatchers.same;
-import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -97,9 +97,8 @@ public class AutoConfiguredLoadBalancerFactoryTest {
@Before
public void setUp() {
- when(testLbBalancer.canHandleEmptyAddressListFromNameResolution()).thenCallRealMethod();
- assertThat(testLbBalancer.canHandleEmptyAddressListFromNameResolution()).isFalse();
- when(testLbBalancer2.canHandleEmptyAddressListFromNameResolution()).thenReturn(true);
+ when(testLbBalancer.acceptResolvedAddresses(isA(ResolvedAddresses.class))).thenReturn(true);
+ when(testLbBalancer2.acceptResolvedAddresses(isA(ResolvedAddresses.class))).thenReturn(true);
defaultRegistry.register(testLbBalancerProvider);
defaultRegistry.register(testLbBalancerProvider2);
}
@@ -171,7 +170,7 @@ public void shutdown() {
}
@Test
- public void handleResolvedAddressGroups_keepOldBalancer() {
+ public void acceptResolvedAddresses_keepOldBalancer() {
final List servers =
Collections.singletonList(new EquivalentAddressGroup(new SocketAddress(){}));
Helper helper = new TestHelper() {
@@ -184,19 +183,19 @@ public Subchannel createSubchannel(CreateSubchannelArgs args) {
AutoConfiguredLoadBalancer lb = lbf.newLoadBalancer(helper);
LoadBalancer oldDelegate = lb.getDelegate();
- Status handleResult = lb.tryHandleResolvedAddresses(
+ boolean addressesAccepted = lb.tryAcceptResolvedAddresses(
ResolvedAddresses.newBuilder()
.setAddresses(servers)
.setAttributes(Attributes.EMPTY)
.setLoadBalancingPolicyConfig(null)
.build());
- assertThat(handleResult.getCode()).isEqualTo(Status.Code.OK);
+ assertThat(addressesAccepted).isTrue();
assertThat(lb.getDelegate()).isSameInstanceAs(oldDelegate);
}
@Test
- public void handleResolvedAddressGroups_shutsDownOldBalancer() throws Exception {
+ public void acceptResolvedAddresses_shutsDownOldBalancer() throws Exception {
Map serviceConfig =
parseConfig("{\"loadBalancingConfig\": [ {\"round_robin\": { } } ] }");
ConfigOrError lbConfigs = lbf.parseLoadBalancerPolicy(serviceConfig);
@@ -226,13 +225,13 @@ public void shutdown() {
};
lb.setDelegate(testlb);
- Status handleResult = lb.tryHandleResolvedAddresses(
+ boolean addressesAccepted = lb.tryAcceptResolvedAddresses(
ResolvedAddresses.newBuilder()
.setAddresses(servers)
.setLoadBalancingPolicyConfig(lbConfigs.getConfig())
.build());
- assertThat(handleResult.getCode()).isEqualTo(Status.Code.OK);
+ assertThat(addressesAccepted).isTrue();
assertThat(lb.getDelegateProvider().getClass().getName()).isEqualTo(
"io.grpc.util.SecretRoundRobinLoadBalancerProvider$Provider");
assertTrue(shutdown.get());
@@ -240,7 +239,7 @@ public void shutdown() {
@Test
@SuppressWarnings("unchecked")
- public void handleResolvedAddressGroups_propagateLbConfigToDelegate() throws Exception {
+ public void acceptResolvedAddresses_propagateLbConfigToDelegate() throws Exception {
Map rawServiceConfig =
parseConfig("{\"loadBalancingConfig\": [ {\"test_lb\": { \"setting1\": \"high\" } } ] }");
ConfigOrError lbConfigs = lbf.parseLoadBalancerPolicy(rawServiceConfig);
@@ -251,20 +250,19 @@ public void handleResolvedAddressGroups_propagateLbConfigToDelegate() throws Exc
Helper helper = new TestHelper();
AutoConfiguredLoadBalancer lb = lbf.newLoadBalancer(helper);
- Status handleResult = lb.tryHandleResolvedAddresses(
+ boolean addressesAccepted = lb.tryAcceptResolvedAddresses(
ResolvedAddresses.newBuilder()
.setAddresses(servers)
.setLoadBalancingPolicyConfig(lbConfigs.getConfig())
.build());
verify(testLbBalancerProvider).newLoadBalancer(same(helper));
- assertThat(handleResult.getCode()).isEqualTo(Status.Code.OK);
+ assertThat(addressesAccepted).isTrue();
assertThat(lb.getDelegate()).isSameInstanceAs(testLbBalancer);
ArgumentCaptor resultCaptor =
ArgumentCaptor.forClass(ResolvedAddresses.class);
- verify(testLbBalancer).handleResolvedAddresses(resultCaptor.capture());
+ verify(testLbBalancer).acceptResolvedAddresses(resultCaptor.capture());
assertThat(resultCaptor.getValue().getAddresses()).containsExactlyElementsIn(servers).inOrder();
- verify(testLbBalancer, atLeast(0)).canHandleEmptyAddressListFromNameResolution();
ArgumentCaptor