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

grpc / grpc-java / #19759

02 Apr 2025 10:52AM UTC coverage: 88.586% (+0.5%) from 88.103%
#19759

push

github

web-flow
core: Delete stale SuppressWarnings("deprecated") for ATTR_LOAD_BALANCING_CONFIG (#11982)

ATTR_LOAD_BALANCING_CONFIG was deleted in bf7a42dbd.

34694 of 39164 relevant lines covered (88.59%)

0.89 hits per line

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

74.12
/../core/src/main/java/io/grpc/internal/AutoConfiguredLoadBalancerFactory.java
1
/*
2
 * Copyright 2018 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.internal;
18

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

21
import com.google.common.annotations.VisibleForTesting;
22
import com.google.common.base.MoreObjects;
23
import io.grpc.ChannelLogger.ChannelLogLevel;
24
import io.grpc.ConnectivityState;
25
import io.grpc.ConnectivityStateInfo;
26
import io.grpc.LoadBalancer;
27
import io.grpc.LoadBalancer.Helper;
28
import io.grpc.LoadBalancer.PickResult;
29
import io.grpc.LoadBalancer.PickSubchannelArgs;
30
import io.grpc.LoadBalancer.ResolvedAddresses;
31
import io.grpc.LoadBalancer.Subchannel;
32
import io.grpc.LoadBalancer.SubchannelPicker;
33
import io.grpc.LoadBalancerProvider;
34
import io.grpc.LoadBalancerRegistry;
35
import io.grpc.NameResolver.ConfigOrError;
36
import io.grpc.Status;
37
import io.grpc.internal.ServiceConfigUtil.LbConfig;
38
import io.grpc.internal.ServiceConfigUtil.PolicySelection;
39
import java.util.List;
40
import java.util.Map;
41
import javax.annotation.Nullable;
42

43
public final class AutoConfiguredLoadBalancerFactory {
44

45
  private final LoadBalancerRegistry registry;
46
  private final String defaultPolicy;
47

48
  public AutoConfiguredLoadBalancerFactory(String defaultPolicy) {
49
    this(LoadBalancerRegistry.getDefaultRegistry(), defaultPolicy);
1✔
50
  }
1✔
51

52
  @VisibleForTesting
53
  AutoConfiguredLoadBalancerFactory(LoadBalancerRegistry registry, String defaultPolicy) {
1✔
54
    this.registry = checkNotNull(registry, "registry");
1✔
55
    this.defaultPolicy = checkNotNull(defaultPolicy, "defaultPolicy");
1✔
56
  }
1✔
57

58
  public AutoConfiguredLoadBalancer newLoadBalancer(Helper helper) {
59
    return new AutoConfiguredLoadBalancer(helper);
1✔
60
  }
61

62
  private static final class NoopLoadBalancer extends LoadBalancer {
63

64
    @Override
65
    @Deprecated
66
    @SuppressWarnings("InlineMeSuggester")
67
    public void handleResolvedAddresses(ResolvedAddresses resolvedAddresses) {
68
    }
×
69

70
    @Override
71
    public Status acceptResolvedAddresses(ResolvedAddresses resolvedAddresses) {
72
      return Status.OK;
×
73
    }
74

75
    @Override
76
    public void handleNameResolutionError(Status error) {}
×
77

78
    @Override
79
    public void shutdown() {}
×
80
  }
81

82
  @VisibleForTesting
83
  public final class AutoConfiguredLoadBalancer {
84
    private final Helper helper;
85
    private LoadBalancer delegate;
86
    private LoadBalancerProvider delegateProvider;
87

88
    AutoConfiguredLoadBalancer(Helper helper) {
1✔
89
      this.helper = helper;
1✔
90
      delegateProvider = registry.getProvider(defaultPolicy);
1✔
91
      if (delegateProvider == null) {
1✔
92
        throw new IllegalStateException("Could not find policy '" + defaultPolicy
×
93
            + "'. Make sure its implementation is either registered to LoadBalancerRegistry or"
94
            + " included in META-INF/services/io.grpc.LoadBalancerProvider from your jar files.");
95
      }
96
      delegate = delegateProvider.newLoadBalancer(helper);
1✔
97
    }
1✔
98

99
    /**
100
     * Returns non-OK status if the delegate rejects the resolvedAddresses (e.g. if it does not
101
     * support an empty list).
102
     */
103
    Status tryAcceptResolvedAddresses(ResolvedAddresses resolvedAddresses) {
104
      PolicySelection policySelection =
1✔
105
          (PolicySelection) resolvedAddresses.getLoadBalancingPolicyConfig();
1✔
106

107
      if (policySelection == null) {
1✔
108
        LoadBalancerProvider defaultProvider;
109
        try {
110
          defaultProvider = getProviderOrThrow(defaultPolicy, "using default policy");
1✔
111
        } catch (PolicyException e) {
×
112
          Status s = Status.INTERNAL.withDescription(e.getMessage());
×
113
          helper.updateBalancingState(ConnectivityState.TRANSIENT_FAILURE, new FailingPicker(s));
×
114
          delegate.shutdown();
×
115
          delegateProvider = null;
×
116
          delegate = new NoopLoadBalancer();
×
117
          return Status.OK;
×
118
        }
1✔
119
        policySelection =
1✔
120
            new PolicySelection(defaultProvider, /* config= */ null);
121
      }
122

123
      if (delegateProvider == null
1✔
124
          || !policySelection.provider.getPolicyName().equals(delegateProvider.getPolicyName())) {
1✔
125
        helper.updateBalancingState(ConnectivityState.CONNECTING, new EmptyPicker());
1✔
126
        delegate.shutdown();
1✔
127
        delegateProvider = policySelection.provider;
1✔
128
        LoadBalancer old = delegate;
1✔
129
        delegate = delegateProvider.newLoadBalancer(helper);
1✔
130
        helper.getChannelLogger().log(
1✔
131
            ChannelLogLevel.INFO, "Load balancer changed from {0} to {1}",
132
            old.getClass().getSimpleName(), delegate.getClass().getSimpleName());
1✔
133
      }
134
      Object lbConfig = policySelection.config;
1✔
135
      if (lbConfig != null) {
1✔
136
        helper.getChannelLogger().log(
1✔
137
            ChannelLogLevel.DEBUG, "Load-balancing config: {0}", policySelection.config);
138
      }
139

140
      return getDelegate().acceptResolvedAddresses(
1✔
141
          ResolvedAddresses.newBuilder()
1✔
142
              .setAddresses(resolvedAddresses.getAddresses())
1✔
143
              .setAttributes(resolvedAddresses.getAttributes())
1✔
144
              .setLoadBalancingPolicyConfig(lbConfig)
1✔
145
              .build());
1✔
146
    }
147

148
    void handleNameResolutionError(Status error) {
149
      getDelegate().handleNameResolutionError(error);
1✔
150
    }
1✔
151

152
    @Deprecated
153
    void handleSubchannelState(Subchannel subchannel, ConnectivityStateInfo stateInfo) {
154
      getDelegate().handleSubchannelState(subchannel, stateInfo);
1✔
155
    }
1✔
156

157
    void requestConnection() {
158
      getDelegate().requestConnection();
1✔
159
    }
1✔
160

161
    void shutdown() {
162
      delegate.shutdown();
1✔
163
      delegate = null;
1✔
164
    }
1✔
165

166
    @VisibleForTesting
167
    public LoadBalancer getDelegate() {
168
      return delegate;
1✔
169
    }
170

171
    @VisibleForTesting
172
    void setDelegate(LoadBalancer lb) {
173
      delegate = lb;
1✔
174
    }
1✔
175

176
    @VisibleForTesting
177
    LoadBalancerProvider getDelegateProvider() {
178
      return delegateProvider;
1✔
179
    }
180
  }
181

182
  private LoadBalancerProvider getProviderOrThrow(String policy, String choiceReason)
183
      throws PolicyException {
184
    LoadBalancerProvider provider = registry.getProvider(policy);
1✔
185
    if (provider == null) {
1✔
186
      throw new PolicyException(
×
187
          "Trying to load '" + policy + "' because " + choiceReason + ", but it's unavailable");
188
    }
189
    return provider;
1✔
190
  }
191

192
  /**
193
   * Parses first available LoadBalancer policy from service config. Available LoadBalancer should
194
   * be registered to {@link LoadBalancerRegistry}. If the first available LoadBalancer policy is
195
   * invalid, it doesn't fall-back to next available policy, instead it returns error. This also
196
   * means, it ignores LoadBalancer policies after the first available one even if any of them are
197
   * invalid.
198
   *
199
   * <p>Order of policy preference:
200
   *
201
   * <ol>
202
   *    <li>Policy from "loadBalancingConfig" if present</li>
203
   *    <li>The policy from deprecated "loadBalancingPolicy" if present</li>
204
   * </ol>
205
   * </p>
206
   *
207
   * <p>Unlike a normal {@link LoadBalancer.Factory}, this accepts a full service config rather than
208
   * the LoadBalancingConfig.
209
   *
210
   * @return the parsed {@link PolicySelection}, or {@code null} if no selection could be made.
211
   */
212
  @Nullable
213
  ConfigOrError parseLoadBalancerPolicy(Map<String, ?> serviceConfig) {
214
    try {
215
      List<LbConfig> loadBalancerConfigs = null;
1✔
216
      if (serviceConfig != null) {
1✔
217
        List<Map<String, ?>> rawLbConfigs =
1✔
218
            ServiceConfigUtil.getLoadBalancingConfigsFromServiceConfig(serviceConfig);
1✔
219
        loadBalancerConfigs = ServiceConfigUtil.unwrapLoadBalancingConfigList(rawLbConfigs);
1✔
220
      }
221
      if (loadBalancerConfigs != null && !loadBalancerConfigs.isEmpty()) {
1✔
222
        return ServiceConfigUtil.selectLbPolicyFromList(loadBalancerConfigs, registry);
1✔
223
      }
224
      return null;
1✔
225
    } catch (RuntimeException e) {
×
226
      return ConfigOrError.fromError(
×
227
          Status.UNKNOWN.withDescription("can't parse load balancer configuration").withCause(e));
×
228
    }
229
  }
230

231
  @VisibleForTesting
232
  static final class PolicyException extends Exception {
233
    private static final long serialVersionUID = 1L;
234

235
    private PolicyException(String msg) {
236
      super(msg);
×
237
    }
×
238
  }
239

240
  private static final class EmptyPicker extends SubchannelPicker {
241

242
    @Override
243
    public PickResult pickSubchannel(PickSubchannelArgs args) {
244
      return PickResult.withNoResult();
1✔
245
    }
246

247
    @Override
248
    public String toString() {
249
      return MoreObjects.toStringHelper(EmptyPicker.class).toString();
1✔
250
    }
251
  }
252

253
  private static final class FailingPicker extends SubchannelPicker {
254
    private final Status failure;
255

256
    FailingPicker(Status failure) {
×
257
      this.failure = failure;
×
258
    }
×
259

260
    @Override
261
    public PickResult pickSubchannel(PickSubchannelArgs args) {
262
      return PickResult.withError(failure);
×
263
    }
264
  }
265
}
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

© 2025 Coveralls, Inc