• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

grpc / grpc-java / #20220

25 Mar 2026 06:04AM UTC coverage: 88.693%. Remained the same
#20220

push

github

web-flow
api: Deprecate LoadBalancer.handleResolvedAddresses() (#11623)

Also deprecate its companion
canHandleEmptyAddressListFromNameResolution().
Also fixup the Javadoc to align with the arguments/return values, so
that people would have a better idea of how to use it.

Fixes #11194

---------

Co-authored-by: MV Shiva Prasad <okshiva@google.com>
Co-authored-by: Eric Anderson <ejona@google.com>

35486 of 40010 relevant lines covered (88.69%)

0.89 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.0
/../grpclb/src/main/java/io/grpc/grpclb/GrpclbLoadBalancer.java
1
/*
2
 * Copyright 2016 The gRPC Authors
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16

17
package io.grpc.grpclb;
18

19
import static com.google.common.base.Preconditions.checkNotNull;
20
import static com.google.common.base.Preconditions.checkState;
21

22
import com.google.common.annotations.VisibleForTesting;
23
import com.google.common.base.Stopwatch;
24
import io.grpc.Attributes;
25
import io.grpc.ChannelLogger.ChannelLogLevel;
26
import io.grpc.Context;
27
import io.grpc.EquivalentAddressGroup;
28
import io.grpc.LoadBalancer;
29
import io.grpc.Status;
30
import io.grpc.grpclb.GrpclbState.Mode;
31
import io.grpc.internal.BackoffPolicy;
32
import io.grpc.internal.TimeProvider;
33
import java.util.ArrayList;
34
import java.util.Collections;
35
import java.util.List;
36
import javax.annotation.Nullable;
37

38
/**
39
 * A {@link LoadBalancer} that uses the GRPCLB protocol.
40
 *
41
 * <p>Optionally, when requested by the naming system, will delegate the work to a local pick-first
42
 * or round-robin balancer.
43
 */
44
class GrpclbLoadBalancer extends LoadBalancer {
45

46
  private static final GrpclbConfig DEFAULT_CONFIG = GrpclbConfig.create(Mode.ROUND_ROBIN);
1✔
47

48
  private final Helper helper;
49
  private final Context context;
50
  private final TimeProvider time;
51
  private final Stopwatch stopwatch;
52
  private final SubchannelPool subchannelPool;
53
  private final BackoffPolicy.Provider backoffPolicyProvider;
54

55
  private GrpclbConfig config = DEFAULT_CONFIG;
1✔
56

57
  // All mutable states in this class are mutated ONLY from Channel Executor
58
  @Nullable
59
  private GrpclbState grpclbState;
60

61
  GrpclbLoadBalancer(
62
      Helper helper,
63
      Context context,
64
      SubchannelPool subchannelPool,
65
      TimeProvider time,
66
      Stopwatch stopwatch,
67
      BackoffPolicy.Provider backoffPolicyProvider) {
1✔
68
    this.helper = checkNotNull(helper, "helper");
1✔
69
    this.context = checkNotNull(context, "context");
1✔
70
    this.time = checkNotNull(time, "time provider");
1✔
71
    this.stopwatch = checkNotNull(stopwatch, "stopwatch");
1✔
72
    this.backoffPolicyProvider = checkNotNull(backoffPolicyProvider, "backoffPolicyProvider");
1✔
73
    this.subchannelPool = checkNotNull(subchannelPool, "subchannelPool");
1✔
74
    recreateStates();
1✔
75
    checkNotNull(grpclbState, "grpclbState");
1✔
76
  }
1✔
77

78
  @Override
79
  public Status acceptResolvedAddresses(ResolvedAddresses resolvedAddresses) {
80
    Attributes attributes = resolvedAddresses.getAttributes();
1✔
81
    List<EquivalentAddressGroup> newLbAddresses = attributes.get(GrpclbConstants.ATTR_LB_ADDRS);
1✔
82
    if (newLbAddresses == null) {
1✔
83
      newLbAddresses = Collections.emptyList();
1✔
84
    }
85
    if (newLbAddresses.isEmpty() && resolvedAddresses.getAddresses().isEmpty()) {
1✔
86
      Status unavailableStatus = Status.UNAVAILABLE.withDescription(
1✔
87
          "No backend or balancer addresses found");
88
      handleNameResolutionError(unavailableStatus);
1✔
89
      return unavailableStatus;
1✔
90
    }
91
    List<EquivalentAddressGroup> overrideAuthorityLbAddresses =
1✔
92
        new ArrayList<>(newLbAddresses.size());
1✔
93
    for (EquivalentAddressGroup lbAddr : newLbAddresses) {
1✔
94
      String lbAddrAuthority = lbAddr.getAttributes().get(GrpclbConstants.ATTR_LB_ADDR_AUTHORITY);
1✔
95
      if (lbAddrAuthority == null) {
1✔
96
        throw new AssertionError(
×
97
            "This is a bug: LB address " + lbAddr + " does not have an authority.");
98
      }
99
      Attributes attrs = lbAddr.getAttributes().toBuilder()
1✔
100
          .set(EquivalentAddressGroup.ATTR_AUTHORITY_OVERRIDE, lbAddrAuthority)
1✔
101
          .build();
1✔
102
      overrideAuthorityLbAddresses.add(new EquivalentAddressGroup(lbAddr.getAddresses(), attrs));
1✔
103
    }
1✔
104

105
    List<EquivalentAddressGroup> newBackendServers =
1✔
106
        Collections.unmodifiableList(resolvedAddresses.getAddresses());
1✔
107
    GrpclbConfig newConfig = (GrpclbConfig) resolvedAddresses.getLoadBalancingPolicyConfig();
1✔
108
    if (newConfig == null) {
1✔
109
      newConfig = DEFAULT_CONFIG;
×
110
    }
111
    if (!config.equals(newConfig)) {
1✔
112
      config = newConfig;
1✔
113
      helper.getChannelLogger().log(ChannelLogLevel.INFO, "Config: " + newConfig);
1✔
114
      recreateStates();
1✔
115
    }
116
    grpclbState.handleAddresses(Collections.unmodifiableList(overrideAuthorityLbAddresses),
1✔
117
        newBackendServers);
118

119
    return Status.OK;
1✔
120
  }
121

122
  @Override
123
  public void requestConnection() {
124
    if (grpclbState != null) {
1✔
125
      grpclbState.requestConnection();
1✔
126
    }
127
  }
1✔
128

129
  private void resetStates() {
130
    if (grpclbState != null) {
1✔
131
      grpclbState.shutdown();
1✔
132
      grpclbState = null;
1✔
133
    }
134
  }
1✔
135

136
  private void recreateStates() {
137
    resetStates();
1✔
138
    checkState(grpclbState == null, "Should've been cleared");
1✔
139
    grpclbState =
1✔
140
        new GrpclbState(
141
            config, helper, context, subchannelPool, time, stopwatch, backoffPolicyProvider);
142
  }
1✔
143

144
  @Override
145
  public void shutdown() {
146
    resetStates();
1✔
147
  }
1✔
148

149
  @Override
150
  public void handleNameResolutionError(Status error) {
151
    if (grpclbState != null) {
1✔
152
      grpclbState.propagateError(error);
1✔
153
    }
154
  }
1✔
155

156
  @Override
157
  @Deprecated
158
  @SuppressWarnings("InlineMeSuggester")
159
  public boolean canHandleEmptyAddressListFromNameResolution() {
160
    return true;
×
161
  }
162

163
  @VisibleForTesting
164
  @Nullable
165
  GrpclbState getGrpclbState() {
166
    return grpclbState;
1✔
167
  }
168
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc