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

grpc / grpc-java / #19916

18 Jul 2025 04:05PM UTC coverage: 88.586% (+0.006%) from 88.58%
#19916

push

github

ejona86
LBs should avoid calling LBs after lb.shutdown()

LoadBalancers shouldn't be called after shutdown(), but RingHashLb could
have enqueued work to the SynchronizationContext that executed after
shutdown(). This commit fixes problems discovered when auditing all LBs
usage of the syncContext for that type of problem.

Similarly, PickFirstLb could have requested a new connection after
shutdown(). We want to avoid that sort of thing too.

RingHashLb's test changed from CONNECTING to TRANSIENT_FAILURE to get
the latest picker. Because two subchannels have failed it will be in
TRANSIENT_FAILURE. Previously the test was using an older picker with
out-of-date subchannelView, and the verifyConnection() was too imprecise
to notice it was creating the wrong subchannel.

As discovered in b/430347751, where ClusterImplLb was seeing a new
subchannel being called after the child LB was shutdown (the shutdown
itself had been caused by RingHashConfig not implementing equals() and
was fixed by a8de9f07ab, which caused ClusterResolverLb to replace its
state):

```
java.lang.NullPointerException
	at io.grpc.xds.ClusterImplLoadBalancer$ClusterImplLbHelper.createClusterLocalityFromAttributes(ClusterImplLoadBalancer.java:322)
	at io.grpc.xds.ClusterImplLoadBalancer$ClusterImplLbHelper.createSubchannel(ClusterImplLoadBalancer.java:236)
	at io.grpc.util.ForwardingLoadBalancerHelper.createSubchannel(ForwardingLoadBalancerHelper.java:47)
	at io.grpc.util.ForwardingLoadBalancerHelper.createSubchannel(ForwardingLoadBalancerHelper.java:47)
	at io.grpc.internal.PickFirstLeafLoadBalancer.createNewSubchannel(PickFirstLeafLoadBalancer.java:527)
	at io.grpc.internal.PickFirstLeafLoadBalancer.requestConnection(PickFirstLeafLoadBalancer.java:459)
	at io.grpc.internal.PickFirstLeafLoadBalancer.acceptResolvedAddresses(PickFirstLeafLoadBalancer.java:174)
	at io.grpc.xds.LazyLoadBalancer$LazyDelegate.activate(LazyLoadBalancer.java:64)
	at io.grpc.xds.LazyLoadBalancer$LazyDelegate.requestConnec... (continued)

34653 of 39118 relevant lines covered (88.59%)

0.89 hits per line

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

79.37
/../api/src/main/java/io/grpc/LoadBalancer.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;
18

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

22
import com.google.common.base.MoreObjects;
23
import com.google.common.base.Objects;
24
import com.google.common.base.Preconditions;
25
import java.util.ArrayList;
26
import java.util.Arrays;
27
import java.util.Collections;
28
import java.util.List;
29
import java.util.Map;
30
import java.util.concurrent.ScheduledExecutorService;
31
import javax.annotation.Nonnull;
32
import javax.annotation.Nullable;
33
import javax.annotation.concurrent.Immutable;
34
import javax.annotation.concurrent.NotThreadSafe;
35
import javax.annotation.concurrent.ThreadSafe;
36

37
/**
38
 * A pluggable component that receives resolved addresses from {@link NameResolver} and provides the
39
 * channel a usable subchannel when asked.
40
 *
41
 * <h3>Overview</h3>
42
 *
43
 * <p>A LoadBalancer typically implements three interfaces:
44
 * <ol>
45
 *   <li>{@link LoadBalancer} is the main interface.  All methods on it are invoked sequentially
46
 *       in the same <strong>synchronization context</strong> (see next section) as returned by
47
 *       {@link io.grpc.LoadBalancer.Helper#getSynchronizationContext}.  It receives the results
48
 *       from the {@link NameResolver}, updates of subchannels' connectivity states, and the
49
 *       channel's request for the LoadBalancer to shutdown.</li>
50
 *   <li>{@link SubchannelPicker SubchannelPicker} does the actual load-balancing work.  It selects
51
 *       a {@link Subchannel Subchannel} for each new RPC.</li>
52
 *   <li>{@link Factory Factory} creates a new {@link LoadBalancer} instance.
53
 * </ol>
54
 *
55
 * <p>{@link Helper Helper} is implemented by gRPC library and provided to {@link Factory
56
 * Factory}. It provides functionalities that a {@code LoadBalancer} implementation would typically
57
 * need.
58
 *
59
 * <h3>The Synchronization Context</h3>
60
 *
61
 * <p>All methods on the {@link LoadBalancer} interface are called from a Synchronization Context,
62
 * meaning they are serialized, thus the balancer implementation doesn't need to worry about
63
 * synchronization among them.  {@link io.grpc.LoadBalancer.Helper#getSynchronizationContext}
64
 * allows implementations to schedule tasks to be run in the same Synchronization Context, with or
65
 * without a delay, thus those tasks don't need to worry about synchronizing with the balancer
66
 * methods.
67
 * 
68
 * <p>However, the actual running thread may be the network thread, thus the following rules must be
69
 * followed to prevent blocking or even dead-locking in a network:
70
 *
71
 * <ol>
72
 *
73
 *   <li><strong>Never block in the Synchronization Context</strong>.  The callback methods must
74
 *   return quickly.  Examples or work that must be avoided: CPU-intensive calculation, waiting on
75
 *   synchronization primitives, blocking I/O, blocking RPCs, etc.</li>
76
 *
77
 *   <li><strong>Avoid calling into other components with lock held</strong>.  The Synchronization
78
 *   Context may be under a lock, e.g., the transport lock of OkHttp.  If your LoadBalancer holds a
79
 *   lock in a callback method (e.g., {@link #handleResolvedAddresses handleResolvedAddresses()})
80
 *   while calling into another method that also involves locks, be cautious of deadlock.  Generally
81
 *   you wouldn't need any locking in the LoadBalancer if you follow the canonical implementation
82
 *   pattern below.</li>
83
 *
84
 * </ol>
85
 *
86
 * <h3>The canonical implementation pattern</h3>
87
 *
88
 * <p>A {@link LoadBalancer} keeps states like the latest addresses from NameResolver, the
89
 * Subchannel(s) and their latest connectivity states.  These states are mutated within the
90
 * Synchronization Context,
91
 *
92
 * <p>A typical {@link SubchannelPicker SubchannelPicker} holds a snapshot of these states.  It may
93
 * have its own states, e.g., a picker from a round-robin load-balancer may keep a pointer to the
94
 * next Subchannel, which are typically mutated by multiple threads.  The picker should only mutate
95
 * its own state, and should not mutate or re-acquire the states of the LoadBalancer.  This way the
96
 * picker only needs to synchronize its own states, which is typically trivial to implement.
97
 *
98
 * <p>When the LoadBalancer states changes, e.g., Subchannels has become or stopped being READY, and
99
 * we want subsequent RPCs to use the latest list of READY Subchannels, LoadBalancer would create a
100
 * new picker, which holds a snapshot of the latest Subchannel list.  Refer to the javadoc of {@link
101
 * io.grpc.LoadBalancer.SubchannelStateListener#onSubchannelState onSubchannelState()} how to do
102
 * this properly.
103
 *
104
 * <p>No synchronization should be necessary between LoadBalancer and its pickers if you follow
105
 * the pattern above.  It may be possible to implement in a different way, but that would usually
106
 * result in more complicated threading.
107
 *
108
 * @since 1.2.0
109
 */
110
@ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
111
@NotThreadSafe
112
public abstract class LoadBalancer {
1✔
113

114
  @Internal
115
  @NameResolver.ResolutionResultAttr
116
  public static final Attributes.Key<Map<String, ?>> ATTR_HEALTH_CHECKING_CONFIG =
1✔
117
      Attributes.Key.create("internal:health-checking-config");
1✔
118

119
  @Internal
120
  public static final LoadBalancer.CreateSubchannelArgs.Key<LoadBalancer.SubchannelStateListener>
121
      HEALTH_CONSUMER_LISTENER_ARG_KEY =
1✔
122
      LoadBalancer.CreateSubchannelArgs.Key.create("internal:health-check-consumer-listener");
1✔
123

124
  @Internal
125
  public static final LoadBalancer.CreateSubchannelArgs.Key<Boolean>
126
      DISABLE_SUBCHANNEL_RECONNECT_KEY =
1✔
127
      LoadBalancer.CreateSubchannelArgs.Key.createWithDefault(
1✔
128
          "internal:disable-subchannel-reconnect", Boolean.FALSE);
129

130
  @Internal
131
  public static final Attributes.Key<Boolean>
132
      HAS_HEALTH_PRODUCER_LISTENER_KEY =
1✔
133
      Attributes.Key.create("internal:has-health-check-producer-listener");
1✔
134

135
  public static final Attributes.Key<Boolean> IS_PETIOLE_POLICY =
1✔
136
      Attributes.Key.create("io.grpc.IS_PETIOLE_POLICY");
1✔
137

138
  /**
139
   * A picker that always returns an erring pick.
140
   *
141
   * @deprecated Use {@code new FixedResultPicker(PickResult.withNoResult())} instead.
142
   */
143
  @Deprecated
144
  public static final SubchannelPicker EMPTY_PICKER = new SubchannelPicker() {
1✔
145
    @Override
146
    public PickResult pickSubchannel(PickSubchannelArgs args) {
147
      return PickResult.withNoResult();
×
148
    }
149

150
    @Override
151
    public String toString() {
152
      return "EMPTY_PICKER";
×
153
    }
154
  };
155

156
  private int recursionCount;
157

158
  /**
159
   * Handles newly resolved server groups and metadata attributes from name resolution system.
160
   * {@code servers} contained in {@link EquivalentAddressGroup} should be considered equivalent
161
   * but may be flattened into a single list if needed.
162
   *
163
   * <p>Implementations should not modify the given {@code servers}.
164
   *
165
   * @param resolvedAddresses the resolved server addresses, attributes, and config.
166
   * @since 1.21.0
167
   */
168
  public void handleResolvedAddresses(ResolvedAddresses resolvedAddresses) {
169
    if (recursionCount++ == 0) {
1✔
170
      // Note that the information about the addresses actually being accepted will be lost
171
      // if you rely on this method for backward compatibility.
172
      acceptResolvedAddresses(resolvedAddresses);
1✔
173
    }
174
    recursionCount = 0;
1✔
175
  }
1✔
176

177
  /**
178
   * Accepts newly resolved addresses from the name resolution system. The {@link
179
   * EquivalentAddressGroup} addresses should be considered equivalent but may be flattened into a
180
   * single list if needed.
181
   *
182
   * <p>Implementations can choose to reject the given addresses by returning {@code false}.
183
   *
184
   * <p>Implementations should not modify the given {@code addresses}.
185
   *
186
   * @param resolvedAddresses the resolved server addresses, attributes, and config.
187
   * @return {@code true} if the resolved addresses were accepted. {@code false} if rejected.
188
   * @since 1.49.0
189
   */
190
  public Status acceptResolvedAddresses(ResolvedAddresses resolvedAddresses) {
191
    if (resolvedAddresses.getAddresses().isEmpty()
1✔
192
        && !canHandleEmptyAddressListFromNameResolution()) {
×
193
      Status unavailableStatus = Status.UNAVAILABLE.withDescription(
×
194
              "NameResolver returned no usable address. addrs=" + resolvedAddresses.getAddresses()
×
195
                      + ", attrs=" + resolvedAddresses.getAttributes());
×
196
      handleNameResolutionError(unavailableStatus);
×
197
      return unavailableStatus;
×
198
    } else {
199
      if (recursionCount++ == 0) {
1✔
200
        handleResolvedAddresses(resolvedAddresses);
×
201
      }
202
      recursionCount = 0;
1✔
203

204
      return Status.OK;
1✔
205
    }
206
  }
207

208
  /**
209
   * Represents a combination of the resolved server address, associated attributes and a load
210
   * balancing policy config.  The config is from the {@link
211
   * LoadBalancerProvider#parseLoadBalancingPolicyConfig(Map)}.
212
   *
213
   * @since 1.21.0
214
   */
215
  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/11657")
216
  public static final class ResolvedAddresses {
217
    private final List<EquivalentAddressGroup> addresses;
218
    @NameResolver.ResolutionResultAttr
219
    private final Attributes attributes;
220
    @Nullable
221
    private final Object loadBalancingPolicyConfig;
222
    // Make sure to update toBuilder() below!
223

224
    private ResolvedAddresses(
225
        List<EquivalentAddressGroup> addresses,
226
        @NameResolver.ResolutionResultAttr Attributes attributes,
227
        Object loadBalancingPolicyConfig) {
1✔
228
      this.addresses =
1✔
229
          Collections.unmodifiableList(new ArrayList<>(checkNotNull(addresses, "addresses")));
1✔
230
      this.attributes = checkNotNull(attributes, "attributes");
1✔
231
      this.loadBalancingPolicyConfig = loadBalancingPolicyConfig;
1✔
232
    }
1✔
233

234
    /**
235
     * Factory for constructing a new Builder.
236
     *
237
     * @since 1.21.0
238
     */
239
    public static Builder newBuilder() {
240
      return new Builder();
1✔
241
    }
242

243
    /**
244
     * Converts this back to a builder.
245
     *
246
     * @since 1.21.0
247
     */
248
    public Builder toBuilder() {
249
      return newBuilder()
1✔
250
          .setAddresses(addresses)
1✔
251
          .setAttributes(attributes)
1✔
252
          .setLoadBalancingPolicyConfig(loadBalancingPolicyConfig);
1✔
253
    }
254

255
    /**
256
     * Gets the server addresses.
257
     *
258
     * @since 1.21.0
259
     */
260
    public List<EquivalentAddressGroup> getAddresses() {
261
      return addresses;
1✔
262
    }
263

264
    /**
265
     * Gets the attributes associated with these addresses.  If this was not previously set,
266
     * {@link Attributes#EMPTY} will be returned.
267
     *
268
     * @since 1.21.0
269
     */
270
    @NameResolver.ResolutionResultAttr
271
    public Attributes getAttributes() {
272
      return attributes;
1✔
273
    }
274

275
    /**
276
     * Gets the domain specific load balancing policy.  This is the config produced by
277
     * {@link LoadBalancerProvider#parseLoadBalancingPolicyConfig(Map)}.
278
     *
279
     * @since 1.21.0
280
     */
281
    @Nullable
282
    public Object getLoadBalancingPolicyConfig() {
283
      return loadBalancingPolicyConfig;
1✔
284
    }
285

286
    /**
287
     * Builder for {@link ResolvedAddresses}.
288
     */
289
    @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
290
    public static final class Builder {
291
      private List<EquivalentAddressGroup> addresses;
292
      @NameResolver.ResolutionResultAttr
1✔
293
      private Attributes attributes = Attributes.EMPTY;
294
      @Nullable
295
      private Object loadBalancingPolicyConfig;
296

297
      Builder() {}
1✔
298

299
      /**
300
       * Sets the addresses.  This field is required.
301
       *
302
       * @return this.
303
       */
304
      public Builder setAddresses(List<EquivalentAddressGroup> addresses) {
305
        this.addresses = addresses;
1✔
306
        return this;
1✔
307
      }
308

309
      /**
310
       * Sets the attributes.  This field is optional; if not called, {@link Attributes#EMPTY}
311
       * will be used.
312
       *
313
       * @return this.
314
       */
315
      public Builder setAttributes(@NameResolver.ResolutionResultAttr Attributes attributes) {
316
        this.attributes = attributes;
1✔
317
        return this;
1✔
318
      }
319

320
      /**
321
       * Sets the load balancing policy config. This field is optional.
322
       *
323
       * @return this.
324
       */
325
      public Builder setLoadBalancingPolicyConfig(@Nullable Object loadBalancingPolicyConfig) {
326
        this.loadBalancingPolicyConfig = loadBalancingPolicyConfig;
1✔
327
        return this;
1✔
328
      }
329

330
      /**
331
       * Constructs the {@link ResolvedAddresses}.
332
       */
333
      public ResolvedAddresses build() {
334
        return new ResolvedAddresses(addresses, attributes, loadBalancingPolicyConfig);
1✔
335
      }
336
    }
337

338
    @Override
339
    public String toString() {
340
      return MoreObjects.toStringHelper(this)
1✔
341
          .add("addresses", addresses)
1✔
342
          .add("attributes", attributes)
1✔
343
          .add("loadBalancingPolicyConfig", loadBalancingPolicyConfig)
1✔
344
          .toString();
1✔
345
    }
346

347
    @Override
348
    public int hashCode() {
349
      return Objects.hashCode(addresses, attributes, loadBalancingPolicyConfig);
×
350
    }
351

352
    @Override
353
    public boolean equals(Object obj) {
354
      if (!(obj instanceof ResolvedAddresses)) {
1✔
355
        return false;
×
356
      }
357
      ResolvedAddresses that = (ResolvedAddresses) obj;
1✔
358
      return Objects.equal(this.addresses, that.addresses)
1✔
359
          && Objects.equal(this.attributes, that.attributes)
1✔
360
          && Objects.equal(this.loadBalancingPolicyConfig, that.loadBalancingPolicyConfig);
1✔
361
    }
362
  }
363

364
  /**
365
   * Handles an error from the name resolution system.
366
   *
367
   * @param error a non-OK status
368
   * @since 1.2.0
369
   */
370
  public abstract void handleNameResolutionError(Status error);
371

372
  /**
373
   * Handles a state change on a Subchannel.
374
   *
375
   * <p>The initial state of a Subchannel is IDLE. You won't get a notification for the initial IDLE
376
   * state.
377
   *
378
   * <p>If the new state is not SHUTDOWN, this method should create a new picker and call {@link
379
   * Helper#updateBalancingState Helper.updateBalancingState()}.  Failing to do so may result in
380
   * unnecessary delays of RPCs. Please refer to {@link PickResult#withSubchannel
381
   * PickResult.withSubchannel()}'s javadoc for more information.
382
   *
383
   * <p>SHUTDOWN can only happen in two cases.  One is that LoadBalancer called {@link
384
   * Subchannel#shutdown} earlier, thus it should have already discarded this Subchannel.  The other
385
   * is that Channel is doing a {@link ManagedChannel#shutdownNow forced shutdown} or has already
386
   * terminated, thus there won't be further requests to LoadBalancer.  Therefore, the LoadBalancer
387
   * usually don't need to react to a SHUTDOWN state.
388
   *
389
   * @param subchannel the involved Subchannel
390
   * @param stateInfo the new state
391
   * @since 1.2.0
392
   * @deprecated This method will be removed.  Stop overriding it.  Instead, pass {@link
393
   *             SubchannelStateListener} to {@link Subchannel#start} to receive Subchannel state
394
   *             updates
395
   */
396
  @Deprecated
397
  public void handleSubchannelState(
398
      Subchannel subchannel, ConnectivityStateInfo stateInfo) {
399
    // Do nothing.  If the implementation doesn't implement this, it will get subchannel states from
400
    // the new API.  We don't throw because there may be forwarding LoadBalancers still plumb this.
401
  }
×
402

403
  /**
404
   * The channel asks the load-balancer to shutdown.  No more methods on this class will be called
405
   * after this method.  The implementation should shutdown all Subchannels and OOB channels, and do
406
   * any other cleanup as necessary.
407
   *
408
   * @since 1.2.0
409
   */
410
  public abstract void shutdown();
411

412
  /**
413
   * Whether this LoadBalancer can handle empty address group list to be passed to {@link
414
   * #handleResolvedAddresses(ResolvedAddresses)}.  The default implementation returns
415
   * {@code false}, meaning that if the NameResolver returns an empty list, the Channel will turn
416
   * that into an error and call {@link #handleNameResolutionError}.  LoadBalancers that want to
417
   * accept empty lists should override this method and return {@code true}.
418
   *
419
   * <p>This method should always return a constant value.  It's not specified when this will be
420
   * called.
421
   */
422
  public boolean canHandleEmptyAddressListFromNameResolution() {
423
    return false;
×
424
  }
425

426
  /**
427
   * The channel asks the LoadBalancer to establish connections now (if applicable) so that the
428
   * upcoming RPC may then just pick a ready connection without waiting for connections.  This
429
   * is triggered by {@link ManagedChannel#getState ManagedChannel.getState(true)}.
430
   *
431
   * <p>If LoadBalancer doesn't override it, this is no-op.  If it infeasible to create connections
432
   * given the current state, e.g. no Subchannel has been created yet, LoadBalancer can ignore this
433
   * request.
434
   *
435
   * @since 1.22.0
436
   */
437
  public void requestConnection() {}
1✔
438

439
  /**
440
   * The main balancing logic.  It <strong>must be thread-safe</strong>. Typically it should only
441
   * synchronize on its own state, and avoid synchronizing with the LoadBalancer's state.
442
   *
443
   * @since 1.2.0
444
   */
445
  @ThreadSafe
446
  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
447
  public abstract static class SubchannelPicker {
1✔
448
    /**
449
     * Make a balancing decision for a new RPC.
450
     *
451
     * @param args the pick arguments
452
     * @since 1.3.0
453
     */
454
    public abstract PickResult pickSubchannel(PickSubchannelArgs args);
455
  }
456

457
  /**
458
   * Provides arguments for a {@link SubchannelPicker#pickSubchannel(
459
   * LoadBalancer.PickSubchannelArgs)}.
460
   *
461
   * @since 1.2.0
462
   */
463
  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
464
  public abstract static class PickSubchannelArgs {
1✔
465

466
    /**
467
     * Call options.
468
     *
469
     * @since 1.2.0
470
     */
471
    public abstract CallOptions getCallOptions();
472

473
    /**
474
     * Headers of the call. {@link SubchannelPicker#pickSubchannel} may mutate it before before
475
     * returning.
476
     *
477
     * @since 1.2.0
478
     */
479
    public abstract Metadata getHeaders();
480

481
    /**
482
     * Call method.
483
     *
484
     * @since 1.2.0
485
     */
486
    public abstract MethodDescriptor<?, ?> getMethodDescriptor();
487

488
    /**
489
     * Gets an object that can be informed about what sort of pick was made.
490
     */
491
    @Internal
492
    public PickDetailsConsumer getPickDetailsConsumer() {
493
      return new PickDetailsConsumer() {};
×
494
    }
495
  }
496

497
  /** Receives information about the pick being chosen. */
498
  @Internal
499
  public interface PickDetailsConsumer {
500
    /**
501
     * Optional labels that provide context of how the pick was routed. Particularly helpful for
502
     * per-RPC metrics.
503
     *
504
     * @throws NullPointerException if key or value is {@code null}
505
     */
506
    default void addOptionalLabel(String key, String value) {
507
      checkNotNull(key, "key");
1✔
508
      checkNotNull(value, "value");
1✔
509
    }
1✔
510
  }
511

512
  /**
513
   * A balancing decision made by {@link SubchannelPicker SubchannelPicker} for an RPC.
514
   *
515
   * <p>The outcome of the decision will be one of the following:
516
   * <ul>
517
   *   <li>Proceed: if a Subchannel is provided via {@link #withSubchannel withSubchannel()}, and is
518
   *       in READY state when the RPC tries to start on it, the RPC will proceed on that
519
   *       Subchannel.</li>
520
   *   <li>Error: if an error is provided via {@link #withError withError()}, and the RPC is not
521
   *       wait-for-ready (i.e., {@link CallOptions#withWaitForReady} was not called), the RPC will
522
   *       fail immediately with the given error.</li>
523
   *   <li>Buffer: in all other cases, the RPC will be buffered in the Channel, until the next
524
   *       picker is provided via {@link Helper#updateBalancingState Helper.updateBalancingState()},
525
   *       when the RPC will go through the same picking process again.</li>
526
   * </ul>
527
   *
528
   * @since 1.2.0
529
   */
530
  @Immutable
531
  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
532
  public static final class PickResult {
533
    private static final PickResult NO_RESULT = new PickResult(null, null, Status.OK, false);
1✔
534

535
    @Nullable private final Subchannel subchannel;
536
    @Nullable private final ClientStreamTracer.Factory streamTracerFactory;
537
    // An error to be propagated to the application if subchannel == null
538
    // Or OK if there is no error.
539
    // subchannel being null and error being OK means RPC needs to wait
540
    private final Status status;
541
    // True if the result is created by withDrop()
542
    private final boolean drop;
543
    @Nullable private final String authorityOverride;
544

545
    private PickResult(
546
        @Nullable Subchannel subchannel, @Nullable ClientStreamTracer.Factory streamTracerFactory,
547
        Status status, boolean drop) {
1✔
548
      this.subchannel = subchannel;
1✔
549
      this.streamTracerFactory = streamTracerFactory;
1✔
550
      this.status = checkNotNull(status, "status");
1✔
551
      this.drop = drop;
1✔
552
      this.authorityOverride = null;
1✔
553
    }
1✔
554

555
    private PickResult(
556
        @Nullable Subchannel subchannel, @Nullable ClientStreamTracer.Factory streamTracerFactory,
557
        Status status, boolean drop, @Nullable String authorityOverride) {
1✔
558
      this.subchannel = subchannel;
1✔
559
      this.streamTracerFactory = streamTracerFactory;
1✔
560
      this.status = checkNotNull(status, "status");
1✔
561
      this.drop = drop;
1✔
562
      this.authorityOverride = authorityOverride;
1✔
563
    }
1✔
564

565
    /**
566
     * A decision to proceed the RPC on a Subchannel.
567
     *
568
     * <p>The Subchannel should either be an original Subchannel returned by {@link
569
     * Helper#createSubchannel Helper.createSubchannel()}, or a wrapper of it preferably based on
570
     * {@code ForwardingSubchannel}.  At the very least its {@link Subchannel#getInternalSubchannel
571
     * getInternalSubchannel()} must return the same object as the one returned by the original.
572
     * Otherwise the Channel cannot use it for the RPC.
573
     *
574
     * <p>When the RPC tries to use the return Subchannel, which is briefly after this method
575
     * returns, the state of the Subchannel will decide where the RPC would go:
576
     *
577
     * <ul>
578
     *   <li>READY: the RPC will proceed on this Subchannel.</li>
579
     *   <li>IDLE: the RPC will be buffered.  Subchannel will attempt to create connection.</li>
580
     *   <li>All other states: the RPC will be buffered.</li>
581
     * </ul>
582
     *
583
     * <p><strong>All buffered RPCs will stay buffered</strong> until the next call of {@link
584
     * Helper#updateBalancingState Helper.updateBalancingState()}, which will trigger a new picking
585
     * process.
586
     *
587
     * <p>Note that Subchannel's state may change at the same time the picker is making the
588
     * decision, which means the decision may be made with (to-be) outdated information.  For
589
     * example, a picker may return a Subchannel known to be READY, but it has become IDLE when is
590
     * about to be used by the RPC, which makes the RPC to be buffered.  The LoadBalancer will soon
591
     * learn about the Subchannels' transition from READY to IDLE, create a new picker and allow the
592
     * RPC to use another READY transport if there is any.
593
     *
594
     * <p>You will want to avoid running into a situation where there are READY Subchannels out
595
     * there but some RPCs are still buffered for longer than a brief time.
596
     * <ul>
597
     *   <li>This can happen if you return Subchannels with states other than READY and IDLE.  For
598
     *       example, suppose you round-robin on 2 Subchannels, in READY and CONNECTING states
599
     *       respectively.  If the picker ignores the state and pick them equally, 50% of RPCs will
600
     *       be stuck in buffered state until both Subchannels are READY.</li>
601
     *   <li>This can also happen if you don't create a new picker at key state changes of
602
     *       Subchannels.  Take the above round-robin example again.  Suppose you do pick only READY
603
     *       and IDLE Subchannels, and initially both Subchannels are READY.  Now one becomes IDLE,
604
     *       then CONNECTING and stays CONNECTING for a long time.  If you don't create a new picker
605
     *       in response to the CONNECTING state to exclude that Subchannel, 50% of RPCs will hit it
606
     *       and be buffered even though the other Subchannel is READY.</li>
607
     * </ul>
608
     *
609
     * <p>In order to prevent unnecessary delay of RPCs, the rules of thumb are:
610
     * <ol>
611
     *   <li>The picker should only pick Subchannels that are known as READY or IDLE.  Whether to
612
     *       pick IDLE Subchannels depends on whether you want Subchannels to connect on-demand or
613
     *       actively:
614
     *       <ul>
615
     *         <li>If you want connect-on-demand, include IDLE Subchannels in your pick results,
616
     *             because when an RPC tries to use an IDLE Subchannel, the Subchannel will try to
617
     *             connect.</li>
618
     *         <li>If you want Subchannels to be always connected even when there is no RPC, you
619
     *             would call {@link Subchannel#requestConnection Subchannel.requestConnection()}
620
     *             whenever the Subchannel has transitioned to IDLE, then you don't need to include
621
     *             IDLE Subchannels in your pick results.</li>
622
     *       </ul></li>
623
     *   <li>Always create a new picker and call {@link Helper#updateBalancingState
624
     *       Helper.updateBalancingState()} whenever {@link #handleSubchannelState
625
     *       handleSubchannelState()} is called, unless the new state is SHUTDOWN. See
626
     *       {@code handleSubchannelState}'s javadoc for more details.</li>
627
     * </ol>
628
     *
629
     * @param subchannel the picked Subchannel.  It must have been {@link Subchannel#start started}
630
     * @param streamTracerFactory if not null, will be used to trace the activities of the stream
631
     *                            created as a result of this pick. Note it's possible that no
632
     *                            stream is created at all in some cases.
633
     * @since 1.3.0
634
     */
635
    public static PickResult withSubchannel(
636
        Subchannel subchannel, @Nullable ClientStreamTracer.Factory streamTracerFactory) {
637
      return new PickResult(
1✔
638
          checkNotNull(subchannel, "subchannel"), streamTracerFactory, Status.OK,
1✔
639
          false);
640
    }
641

642
    /**
643
     * Same as {@code withSubchannel(subchannel, streamTracerFactory)} but with an authority name
644
     * to override in the host header.
645
     */
646
    @ExperimentalApi("https://github.com/grpc/grpc-java/issues/11656")
647
    public static PickResult withSubchannel(
648
        Subchannel subchannel, @Nullable ClientStreamTracer.Factory streamTracerFactory,
649
        @Nullable String authorityOverride) {
650
      return new PickResult(
1✔
651
          checkNotNull(subchannel, "subchannel"), streamTracerFactory, Status.OK,
1✔
652
          false, authorityOverride);
653
    }
654

655
    /**
656
     * Equivalent to {@code withSubchannel(subchannel, null)}.
657
     *
658
     * @since 1.2.0
659
     */
660
    public static PickResult withSubchannel(Subchannel subchannel) {
661
      return withSubchannel(subchannel, null);
1✔
662
    }
663

664
    /**
665
     * A decision to report a connectivity error to the RPC.  If the RPC is {@link
666
     * CallOptions#withWaitForReady wait-for-ready}, it will stay buffered.  Otherwise, it will fail
667
     * with the given error.
668
     *
669
     * @param error the error status.  Must not be OK.
670
     * @since 1.2.0
671
     */
672
    public static PickResult withError(Status error) {
673
      Preconditions.checkArgument(!error.isOk(), "error status shouldn't be OK");
1✔
674
      return new PickResult(null, null, error, false);
1✔
675
    }
676

677
    /**
678
     * A decision to fail an RPC immediately.  This is a final decision and will ignore retry
679
     * policy.
680
     *
681
     * @param status the status with which the RPC will fail.  Must not be OK.
682
     * @since 1.8.0
683
     */
684
    public static PickResult withDrop(Status status) {
685
      Preconditions.checkArgument(!status.isOk(), "drop status shouldn't be OK");
1✔
686
      return new PickResult(null, null, status, true);
1✔
687
    }
688

689
    /**
690
     * No decision could be made.  The RPC will stay buffered.
691
     *
692
     * @since 1.2.0
693
     */
694
    public static PickResult withNoResult() {
695
      return NO_RESULT;
1✔
696
    }
697

698
    /** Returns the authority override if any. */
699
    @ExperimentalApi("https://github.com/grpc/grpc-java/issues/11656")
700
    @Nullable
701
    public String getAuthorityOverride() {
702
      return authorityOverride;
1✔
703
    }
704

705
    /**
706
     * The Subchannel if this result was created by {@link #withSubchannel withSubchannel()}, or
707
     * null otherwise.
708
     *
709
     * @since 1.2.0
710
     */
711
    @Nullable
712
    public Subchannel getSubchannel() {
713
      return subchannel;
1✔
714
    }
715

716
    /**
717
     * The stream tracer factory this result was created with.
718
     *
719
     * @since 1.3.0
720
     */
721
    @Nullable
722
    public ClientStreamTracer.Factory getStreamTracerFactory() {
723
      return streamTracerFactory;
1✔
724
    }
725

726
    /**
727
     * The status associated with this result.  Non-{@code OK} if created with {@link #withError
728
     * withError}, or {@code OK} otherwise.
729
     *
730
     * @since 1.2.0
731
     */
732
    public Status getStatus() {
733
      return status;
1✔
734
    }
735

736
    /**
737
     * Returns {@code true} if this result was created by {@link #withDrop withDrop()}.
738
     *
739
     * @since 1.8.0
740
     */
741
    public boolean isDrop() {
742
      return drop;
1✔
743
    }
744

745
    /**
746
     * Returns {@code true} if the pick was not created with {@link #withNoResult()}.
747
     */
748
    public boolean hasResult() {
749
      return !(subchannel == null && status.isOk());
1✔
750
    }
751

752
    @Override
753
    public String toString() {
754
      return MoreObjects.toStringHelper(this)
1✔
755
          .add("subchannel", subchannel)
1✔
756
          .add("streamTracerFactory", streamTracerFactory)
1✔
757
          .add("status", status)
1✔
758
          .add("drop", drop)
1✔
759
          .add("authority-override", authorityOverride)
1✔
760
          .toString();
1✔
761
    }
762

763
    @Override
764
    public int hashCode() {
765
      return Objects.hashCode(subchannel, status, streamTracerFactory, drop);
1✔
766
    }
767

768
    /**
769
     * Returns true if the {@link Subchannel}, {@link Status}, and
770
     * {@link ClientStreamTracer.Factory} all match.
771
     */
772
    @Override
773
    public boolean equals(Object other) {
774
      if (!(other instanceof PickResult)) {
1✔
775
        return false;
×
776
      }
777
      PickResult that = (PickResult) other;
1✔
778
      return Objects.equal(subchannel, that.subchannel) && Objects.equal(status, that.status)
1✔
779
          && Objects.equal(streamTracerFactory, that.streamTracerFactory)
1✔
780
          && drop == that.drop;
781
    }
782
  }
783

784
  /**
785
   * Arguments for creating a {@link Subchannel}.
786
   *
787
   * @since 1.22.0
788
   */
789
  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
790
  public static final class CreateSubchannelArgs {
791
    private final List<EquivalentAddressGroup> addrs;
792
    private final Attributes attrs;
793
    private final Object[][] customOptions;
794

795
    private CreateSubchannelArgs(
796
        List<EquivalentAddressGroup> addrs, Attributes attrs, Object[][] customOptions) {
1✔
797
      this.addrs = checkNotNull(addrs, "addresses are not set");
1✔
798
      this.attrs = checkNotNull(attrs, "attrs");
1✔
799
      this.customOptions = checkNotNull(customOptions, "customOptions");
1✔
800
    }
1✔
801

802
    /**
803
     * Returns the addresses, which is an unmodifiable list.
804
     */
805
    public List<EquivalentAddressGroup> getAddresses() {
806
      return addrs;
1✔
807
    }
808

809
    /**
810
     * Returns the attributes.
811
     */
812
    public Attributes getAttributes() {
813
      return attrs;
1✔
814
    }
815

816
    /**
817
     * Get the value for a custom option or its inherent default.
818
     *
819
     * @param key Key identifying option
820
     */
821
    @SuppressWarnings("unchecked")
822
    public <T> T getOption(Key<T> key) {
823
      Preconditions.checkNotNull(key, "key");
1✔
824
      for (int i = 0; i < customOptions.length; i++) {
1✔
825
        if (key.equals(customOptions[i][0])) {
1✔
826
          return (T) customOptions[i][1];
1✔
827
        }
828
      }
829
      return key.defaultValue;
1✔
830
    }
831

832
    /**
833
     * Returns a builder with the same initial values as this object.
834
     */
835
    public Builder toBuilder() {
836
      return newBuilder().setAddresses(addrs).setAttributes(attrs).copyCustomOptions(customOptions);
1✔
837
    }
838

839
    /**
840
     * Creates a new builder.
841
     */
842
    public static Builder newBuilder() {
843
      return new Builder();
1✔
844
    }
845

846
    @Override
847
    public String toString() {
848
      return MoreObjects.toStringHelper(this)
1✔
849
          .add("addrs", addrs)
1✔
850
          .add("attrs", attrs)
1✔
851
          .add("customOptions", Arrays.deepToString(customOptions))
1✔
852
          .toString();
1✔
853
    }
854

855
    @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
856
    public static final class Builder {
857

858
      private List<EquivalentAddressGroup> addrs;
859
      private Attributes attrs = Attributes.EMPTY;
1✔
860
      private Object[][] customOptions = new Object[0][2];
1✔
861

862
      Builder() {
1✔
863
      }
1✔
864

865
      private Builder copyCustomOptions(Object[][] options) {
866
        customOptions = new Object[options.length][2];
1✔
867
        System.arraycopy(options, 0, customOptions, 0, options.length);
1✔
868
        return this;
1✔
869
      }
870

871
      /**
872
       * Add a custom option. Any existing value for the key is overwritten.
873
       *
874
       * <p>This is an <strong>optional</strong> property.
875
       *
876
       * @param key the option key
877
       * @param value the option value
878
       */
879
      public <T> Builder addOption(Key<T> key, T value) {
880
        Preconditions.checkNotNull(key, "key");
1✔
881
        Preconditions.checkNotNull(value, "value");
1✔
882

883
        int existingIdx = -1;
1✔
884
        for (int i = 0; i < customOptions.length; i++) {
1✔
885
          if (key.equals(customOptions[i][0])) {
1✔
886
            existingIdx = i;
1✔
887
            break;
1✔
888
          }
889
        }
890

891
        if (existingIdx == -1) {
1✔
892
          Object[][] newCustomOptions = new Object[customOptions.length + 1][2];
1✔
893
          System.arraycopy(customOptions, 0, newCustomOptions, 0, customOptions.length);
1✔
894
          customOptions = newCustomOptions;
1✔
895
          existingIdx = customOptions.length - 1;
1✔
896
        }
897
        customOptions[existingIdx] = new Object[]{key, value};
1✔
898
        return this;
1✔
899
      }
900

901
      /**
902
       * The addresses to connect to.  All addresses are considered equivalent and will be tried
903
       * in the order they are provided.
904
       */
905
      public Builder setAddresses(EquivalentAddressGroup addrs) {
906
        this.addrs = Collections.singletonList(addrs);
1✔
907
        return this;
1✔
908
      }
909

910
      /**
911
       * The addresses to connect to.  All addresses are considered equivalent and will
912
       * be tried in the order they are provided.
913
       *
914
       * <p>This is a <strong>required</strong> property.
915
       *
916
       * @throws IllegalArgumentException if {@code addrs} is empty
917
       */
918
      public Builder setAddresses(List<EquivalentAddressGroup> addrs) {
919
        checkArgument(!addrs.isEmpty(), "addrs is empty");
1✔
920
        this.addrs = Collections.unmodifiableList(new ArrayList<>(addrs));
1✔
921
        return this;
1✔
922
      }
923

924
      /**
925
       * Attributes provided here will be included in {@link Subchannel#getAttributes}.
926
       *
927
       * <p>This is an <strong>optional</strong> property.  Default is empty if not set.
928
       */
929
      public Builder setAttributes(Attributes attrs) {
930
        this.attrs = checkNotNull(attrs, "attrs");
1✔
931
        return this;
1✔
932
      }
933

934
      /**
935
       * Creates a new args object.
936
       */
937
      public CreateSubchannelArgs build() {
938
        return new CreateSubchannelArgs(addrs, attrs, customOptions);
1✔
939
      }
940
    }
941

942
    /**
943
     * Key for a key-value pair. Uses reference equality.
944
     */
945
    @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
946
    public static final class Key<T> {
947

948
      private final String debugString;
949
      private final T defaultValue;
950

951
      private Key(String debugString, T defaultValue) {
1✔
952
        this.debugString = debugString;
1✔
953
        this.defaultValue = defaultValue;
1✔
954
      }
1✔
955

956
      /**
957
       * Factory method for creating instances of {@link Key}. The default value of the key is
958
       * {@code null}.
959
       *
960
       * @param debugString a debug string that describes this key.
961
       * @param <T> Key type
962
       * @return Key object
963
       */
964
      public static <T> Key<T> create(String debugString) {
965
        Preconditions.checkNotNull(debugString, "debugString");
1✔
966
        return new Key<>(debugString, /*defaultValue=*/ null);
1✔
967
      }
968

969
      /**
970
       * Factory method for creating instances of {@link Key}.
971
       *
972
       * @param debugString a debug string that describes this key.
973
       * @param defaultValue default value to return when value for key not set
974
       * @param <T> Key type
975
       * @return Key object
976
       */
977
      public static <T> Key<T> createWithDefault(String debugString, T defaultValue) {
978
        Preconditions.checkNotNull(debugString, "debugString");
1✔
979
        return new Key<>(debugString, defaultValue);
1✔
980
      }
981

982
      /**
983
       * Returns the user supplied default value for this key.
984
       */
985
      public T getDefault() {
986
        return defaultValue;
×
987
      }
988

989
      @Override
990
      public String toString() {
991
        return debugString;
1✔
992
      }
993
    }
994
  }
995

996
  /**
997
   * Provides essentials for LoadBalancer implementations.
998
   *
999
   * @since 1.2.0
1000
   */
1001
  @ThreadSafe
1002
  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
1003
  public abstract static class Helper {
1✔
1004
    /**
1005
     * Creates a Subchannel, which is a logical connection to the given group of addresses which are
1006
     * considered equivalent.  The {@code attrs} are custom attributes associated with this
1007
     * Subchannel, and can be accessed later through {@link Subchannel#getAttributes
1008
     * Subchannel.getAttributes()}.
1009
     *
1010
     * <p>The LoadBalancer is responsible for closing unused Subchannels, and closing all
1011
     * Subchannels within {@link #shutdown}.
1012
     *
1013
     * <p>It must be called from {@link #getSynchronizationContext the Synchronization Context}
1014
     *
1015
     * @return Must return a valid Subchannel object, may not return null.
1016
     *
1017
     * @since 1.22.0
1018
     */
1019
    public Subchannel createSubchannel(CreateSubchannelArgs args) {
1020
      throw new UnsupportedOperationException();
1✔
1021
    }
1022

1023
    /**
1024
     * Create an out-of-band channel for the LoadBalancer’s own RPC needs, e.g., talking to an
1025
     * external load-balancer service.
1026
     *
1027
     * <p>The LoadBalancer is responsible for closing unused OOB channels, and closing all OOB
1028
     * channels within {@link #shutdown}.
1029
     *
1030
     * @since 1.4.0
1031
     */
1032
    public abstract ManagedChannel createOobChannel(EquivalentAddressGroup eag, String authority);
1033

1034
    /**
1035
     * Create an out-of-band channel for the LoadBalancer's own RPC needs, e.g., talking to an
1036
     * external load-balancer service. This version of the method allows multiple EAGs, so different
1037
     * addresses can have different authorities.
1038
     *
1039
     * <p>The LoadBalancer is responsible for closing unused OOB channels, and closing all OOB
1040
     * channels within {@link #shutdown}.
1041
     * */
1042
    public ManagedChannel createOobChannel(List<EquivalentAddressGroup> eag,
1043
        String authority) {
1044
      throw new UnsupportedOperationException();
×
1045
    }
1046

1047
    /**
1048
     * Updates the addresses used for connections in the {@code Channel} that was created by {@link
1049
     * #createOobChannel(EquivalentAddressGroup, String)}. This is superior to {@link
1050
     * #createOobChannel(EquivalentAddressGroup, String)} when the old and new addresses overlap,
1051
     * since the channel can continue using an existing connection.
1052
     *
1053
     * @throws IllegalArgumentException if {@code channel} was not returned from {@link
1054
     *     #createOobChannel}
1055
     * @since 1.4.0
1056
     */
1057
    public void updateOobChannelAddresses(ManagedChannel channel, EquivalentAddressGroup eag) {
1058
      throw new UnsupportedOperationException();
×
1059
    }
1060

1061
    /**
1062
     * Updates the addresses with a new EAG list. Connection is continued when old and new addresses
1063
     * overlap.
1064
     * */
1065
    public void updateOobChannelAddresses(ManagedChannel channel,
1066
        List<EquivalentAddressGroup> eag) {
1067
      throw new UnsupportedOperationException();
×
1068
    }
1069

1070
    /**
1071
     * Creates an out-of-band channel for LoadBalancer's own RPC needs, e.g., talking to an external
1072
     * load-balancer service, that is specified by a target string.  See the documentation on
1073
     * {@link ManagedChannelBuilder#forTarget} for the format of a target string.
1074
     *
1075
     * <p>The target string will be resolved by a {@link NameResolver} created according to the
1076
     * target string.
1077
     *
1078
     * <p>The LoadBalancer is responsible for closing unused OOB channels, and closing all OOB
1079
     * channels within {@link #shutdown}.
1080
     *
1081
     * @since 1.20.0
1082
     */
1083
    public ManagedChannel createResolvingOobChannel(String target) {
1084
      return createResolvingOobChannelBuilder(target).build();
1✔
1085
    }
1086

1087
    /**
1088
     * Creates an out-of-band channel builder for LoadBalancer's own RPC needs, e.g., talking to an
1089
     * external load-balancer service, that is specified by a target string.  See the documentation
1090
     * on {@link ManagedChannelBuilder#forTarget} for the format of a target string.
1091
     *
1092
     * <p>The target string will be resolved by a {@link NameResolver} created according to the
1093
     * target string.
1094
     *
1095
     * <p>The returned oob-channel builder defaults to use the same authority and ChannelCredentials
1096
     * (without bearer tokens) as the parent channel's for authentication. This is different from
1097
     * {@link #createResolvingOobChannelBuilder(String, ChannelCredentials)}.
1098
     *
1099
     * <p>The LoadBalancer is responsible for closing unused OOB channels, and closing all OOB
1100
     * channels within {@link #shutdown}.
1101
     *
1102
     * @deprecated Use {@link #createResolvingOobChannelBuilder(String, ChannelCredentials)}
1103
     *     instead.
1104
     * @since 1.31.0
1105
     */
1106
    @Deprecated
1107
    public ManagedChannelBuilder<?> createResolvingOobChannelBuilder(String target) {
1108
      throw new UnsupportedOperationException("Not implemented");
×
1109
    }
1110

1111
    /**
1112
     * Creates an out-of-band channel builder for LoadBalancer's own RPC needs, e.g., talking to an
1113
     * external load-balancer service, that is specified by a target string and credentials.  See
1114
     * the documentation on {@link Grpc#newChannelBuilder} for the format of a target string.
1115
     *
1116
     * <p>The target string will be resolved by a {@link NameResolver} created according to the
1117
     * target string.
1118
     *
1119
     * <p>The LoadBalancer is responsible for closing unused OOB channels, and closing all OOB
1120
     * channels within {@link #shutdown}.
1121
     *
1122
     * @since 1.35.0
1123
     */
1124
    public ManagedChannelBuilder<?> createResolvingOobChannelBuilder(
1125
        String target, ChannelCredentials creds) {
1126
      throw new UnsupportedOperationException();
×
1127
    }
1128

1129
    /**
1130
     * Set a new state with a new picker to the channel.
1131
     *
1132
     * <p>When a new picker is provided via {@code updateBalancingState()}, the channel will apply
1133
     * the picker on all buffered RPCs, by calling {@link SubchannelPicker#pickSubchannel(
1134
     * LoadBalancer.PickSubchannelArgs)}.
1135
     *
1136
     * <p>The channel will hold the picker and use it for all RPCs, until {@code
1137
     * updateBalancingState()} is called again and a new picker replaces the old one.  If {@code
1138
     * updateBalancingState()} has never been called, the channel will buffer all RPCs until a
1139
     * picker is provided.
1140
     *
1141
     * <p>It should be called from the Synchronization Context.  Currently will log a warning if
1142
     * violated.  It will become an exception eventually.  See <a
1143
     * href="https://github.com/grpc/grpc-java/issues/5015">#5015</a> for the background.
1144
     *
1145
     * <p>The passed state will be the channel's new state. The SHUTDOWN state should not be passed
1146
     * and its behavior is undefined.
1147
     *
1148
     * @since 1.6.0
1149
     */
1150
    public abstract void updateBalancingState(
1151
        @Nonnull ConnectivityState newState, @Nonnull SubchannelPicker newPicker);
1152

1153
    /**
1154
     * Call {@link NameResolver#refresh} on the channel's resolver.
1155
     *
1156
     * <p>It should be called from the Synchronization Context.  Currently will log a warning if
1157
     * violated.  It will become an exception eventually.  See <a
1158
     * href="https://github.com/grpc/grpc-java/issues/5015">#5015</a> for the background.
1159
     *
1160
     * @since 1.18.0
1161
     */
1162
    public void refreshNameResolution() {
1163
      throw new UnsupportedOperationException();
×
1164
    }
1165

1166
    /**
1167
     * Historically the channel automatically refreshes name resolution if any subchannel
1168
     * connection is broken. It's transitioning to let load balancers make the decision. To
1169
     * avoid silent breakages, the channel checks if {@link #refreshNameResolution} is called
1170
     * by the load balancer. If not, it will do it and log a warning. This will be removed in
1171
     * the future and load balancers are completely responsible for triggering the refresh.
1172
     * See <a href="https://github.com/grpc/grpc-java/issues/8088">#8088</a> for the background.
1173
     *
1174
     * <p>This should rarely be used, but sometimes the address for the subchannel wasn't
1175
     * provided by the name resolver and a refresh needs to be directed somewhere else instead.
1176
     * Then you can call this method to disable the short-tem check for detecting LoadBalancers
1177
     * that need to be updated for the new expected behavior.
1178
     *
1179
     * @since 1.38.0
1180
     * @deprecated Warning has been removed
1181
     */
1182
    @ExperimentalApi("https://github.com/grpc/grpc-java/issues/8088")
1183
    @Deprecated
1184
    public void ignoreRefreshNameResolutionCheck() {
1185
      // no-op
1186
    }
×
1187

1188
    /**
1189
     * Returns a {@link SynchronizationContext} that runs tasks in the same Synchronization Context
1190
     * as that the callback methods on the {@link LoadBalancer} interface are run in.
1191
     *
1192
     * <p>Work added to the synchronization context might not run immediately, so LB implementations
1193
     * must be careful to ensure that any assumptions still hold when it is executed. In particular,
1194
     * the LB might have been shut down or subchannels might have changed state.
1195
     *
1196
     * <p>Pro-tip: in order to call {@link SynchronizationContext#schedule}, you need to provide a
1197
     * {@link ScheduledExecutorService}.  {@link #getScheduledExecutorService} is provided for your
1198
     * convenience.
1199
     *
1200
     * @since 1.17.0
1201
     */
1202
    public SynchronizationContext getSynchronizationContext() {
1203
      // TODO(zhangkun): make getSynchronizationContext() abstract after runSerialized() is deleted
1204
      throw new UnsupportedOperationException();
×
1205
    }
1206

1207
    /**
1208
     * Returns a {@link ScheduledExecutorService} for scheduling delayed tasks.
1209
     *
1210
     * <p>This service is a shared resource and is only meant for quick tasks.  DO NOT block or run
1211
     * time-consuming tasks.
1212
     *
1213
     * <p>The returned service doesn't support {@link ScheduledExecutorService#shutdown shutdown()}
1214
     * and {@link ScheduledExecutorService#shutdownNow shutdownNow()}.  They will throw if called.
1215
     *
1216
     * @since 1.17.0
1217
     */
1218
    public ScheduledExecutorService getScheduledExecutorService() {
1219
      throw new UnsupportedOperationException();
×
1220
    }
1221

1222
    /**
1223
     * Returns the authority string of the channel, which is derived from the DNS-style target name.
1224
     * If overridden by a load balancer, {@link #getUnsafeChannelCredentials} must also be
1225
     * overridden to call {@link #getChannelCredentials} or provide appropriate credentials.
1226
     *
1227
     * @since 1.2.0
1228
     */
1229
    public abstract String getAuthority();
1230

1231
    /**
1232
     * Returns the target string of the channel, guaranteed to include its scheme.
1233
     */
1234
    public String getChannelTarget() {
1235
      throw new UnsupportedOperationException();
×
1236
    }
1237

1238
    /**
1239
     * Returns the ChannelCredentials used to construct the channel, without bearer tokens.
1240
     *
1241
     * @since 1.35.0
1242
     */
1243
    public ChannelCredentials getChannelCredentials() {
1244
      return getUnsafeChannelCredentials().withoutBearerTokens();
×
1245
    }
1246

1247
    /**
1248
     * Returns the UNSAFE ChannelCredentials used to construct the channel,
1249
     * including bearer tokens. Load balancers should generally have no use for
1250
     * these credentials and use of them is heavily discouraged. These must be used
1251
     * <em>very</em> carefully to avoid sending bearer tokens to untrusted servers
1252
     * as the server could then impersonate the client. Generally it is only safe
1253
     * to use these credentials when communicating with the backend.
1254
     *
1255
     * @since 1.35.0
1256
     */
1257
    public ChannelCredentials getUnsafeChannelCredentials() {
1258
      throw new UnsupportedOperationException();
×
1259
    }
1260

1261
    /**
1262
     * Returns the {@link ChannelLogger} for the Channel served by this LoadBalancer.
1263
     *
1264
     * @since 1.17.0
1265
     */
1266
    public ChannelLogger getChannelLogger() {
1267
      throw new UnsupportedOperationException();
×
1268
    }
1269

1270
    /**
1271
     * Returns the {@link NameResolver.Args} that the Channel uses to create {@link NameResolver}s.
1272
     *
1273
     * @since 1.22.0
1274
     */
1275
    public NameResolver.Args getNameResolverArgs() {
1276
      throw new UnsupportedOperationException();
×
1277
    }
1278

1279
    /**
1280
     * Returns the {@link NameResolverRegistry} that the Channel uses to look for {@link
1281
     * NameResolver}s.
1282
     *
1283
     * @since 1.22.0
1284
     */
1285
    public NameResolverRegistry getNameResolverRegistry() {
1286
      throw new UnsupportedOperationException();
×
1287
    }
1288

1289
    /**
1290
     * Returns the {@link MetricRecorder} that the channel uses to record metrics.
1291
     *
1292
     * @since 1.64.0
1293
     */
1294
    @Internal
1295
    public MetricRecorder getMetricRecorder() {
1296
      return new MetricRecorder() {};
×
1297
    }
1298
  }
1299

1300
  /**
1301
   * A logical connection to a server, or a group of equivalent servers represented by an {@link 
1302
   * EquivalentAddressGroup}.
1303
   *
1304
   * <p>It maintains at most one physical connection (aka transport) for sending new RPCs, while
1305
   * also keeps track of previous transports that has been shut down but not terminated yet.
1306
   *
1307
   * <p>If there isn't an active transport yet, and an RPC is assigned to the Subchannel, it will
1308
   * create a new transport.  It won't actively create transports otherwise.  {@link
1309
   * #requestConnection requestConnection()} can be used to ask Subchannel to create a transport if
1310
   * there isn't any.
1311
   *
1312
   * <p>{@link #start} must be called prior to calling any other methods, with the exception of
1313
   * {@link #shutdown}, which can be called at any time.
1314
   *
1315
   * @since 1.2.0
1316
   */
1317
  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
1318
  public abstract static class Subchannel {
1✔
1319
    /**
1320
     * Starts the Subchannel.  Can only be called once.
1321
     *
1322
     * <p>Must be called prior to any other method on this class, except for {@link #shutdown} which
1323
     * may be called at any time.
1324
     *
1325
     * <p>Must be called from the {@link Helper#getSynchronizationContext Synchronization Context},
1326
     * otherwise it may throw.  See <a href="https://github.com/grpc/grpc-java/issues/5015">
1327
     * #5015</a> for more discussions.
1328
     *
1329
     * @param listener receives state updates for this Subchannel.
1330
     */
1331
    public void start(SubchannelStateListener listener) {
1332
      throw new UnsupportedOperationException("Not implemented");
×
1333
    }
1334

1335
    /**
1336
     * Shuts down the Subchannel.  After this method is called, this Subchannel should no longer
1337
     * be returned by the latest {@link SubchannelPicker picker}, and can be safely discarded.
1338
     *
1339
     * <p>Calling it on an already shut-down Subchannel has no effect.
1340
     *
1341
     * <p>It should be called from the Synchronization Context.  Currently will log a warning if
1342
     * violated.  It will become an exception eventually.  See <a
1343
     * href="https://github.com/grpc/grpc-java/issues/5015">#5015</a> for the background.
1344
     *
1345
     * @since 1.2.0
1346
     */
1347
    public abstract void shutdown();
1348

1349
    /**
1350
     * Asks the Subchannel to create a connection (aka transport), if there isn't an active one.
1351
     *
1352
     * <p>It should be called from the Synchronization Context.  Currently will log a warning if
1353
     * violated.  It will become an exception eventually.  See <a
1354
     * href="https://github.com/grpc/grpc-java/issues/5015">#5015</a> for the background.
1355
     *
1356
     * @since 1.2.0
1357
     */
1358
    public abstract void requestConnection();
1359

1360
    /**
1361
     * Returns the addresses that this Subchannel is bound to.  This can be called only if
1362
     * the Subchannel has only one {@link EquivalentAddressGroup}.  Under the hood it calls
1363
     * {@link #getAllAddresses}.
1364
     *
1365
     * <p>It should be called from the Synchronization Context.  Currently will log a warning if
1366
     * violated.  It will become an exception eventually.  See <a
1367
     * href="https://github.com/grpc/grpc-java/issues/5015">#5015</a> for the background.
1368
     *
1369
     * @throws IllegalStateException if this subchannel has more than one EquivalentAddressGroup.
1370
     *         Use {@link #getAllAddresses} instead
1371
     * @since 1.2.0
1372
     */
1373
    public final EquivalentAddressGroup getAddresses() {
1374
      List<EquivalentAddressGroup> groups = getAllAddresses();
1✔
1375
      Preconditions.checkState(groups != null && groups.size() == 1,
1✔
1376
          "%s does not have exactly one group", groups);
1377
      return groups.get(0);
1✔
1378
    }
1379

1380
    /**
1381
     * Returns the addresses that this Subchannel is bound to. The returned list will not be empty.
1382
     *
1383
     * <p>It should be called from the Synchronization Context.  Currently will log a warning if
1384
     * violated.  It will become an exception eventually.  See <a
1385
     * href="https://github.com/grpc/grpc-java/issues/5015">#5015</a> for the background.
1386
     *
1387
     * @since 1.14.0
1388
     */
1389
    public List<EquivalentAddressGroup> getAllAddresses() {
1390
      throw new UnsupportedOperationException();
×
1391
    }
1392

1393
    /**
1394
     * The same attributes passed to {@link Helper#createSubchannel Helper.createSubchannel()}.
1395
     * LoadBalancer can use it to attach additional information here, e.g., the shard this
1396
     * Subchannel belongs to.
1397
     *
1398
     * @since 1.2.0
1399
     */
1400
    public abstract Attributes getAttributes();
1401

1402
    /**
1403
     * (Internal use only) returns a {@link Channel} that is backed by this Subchannel.  This allows
1404
     * a LoadBalancer to issue its own RPCs for auxiliary purposes, such as health-checking, on
1405
     * already-established connections.  This channel has certain restrictions:
1406
     * <ol>
1407
     *   <li>It can issue RPCs only if the Subchannel is {@code READY}. If {@link
1408
     *   Channel#newCall} is called when the Subchannel is not {@code READY}, the RPC will fail
1409
     *   immediately.</li>
1410
     *   <li>It doesn't support {@link CallOptions#withWaitForReady wait-for-ready} RPCs. Such RPCs
1411
     *   will fail immediately.</li>
1412
     * </ol>
1413
     *
1414
     * <p>RPCs made on this Channel is not counted when determining ManagedChannel's {@link
1415
     * ManagedChannelBuilder#idleTimeout idle mode}.  In other words, they won't prevent
1416
     * ManagedChannel from entering idle mode.
1417
     *
1418
     * <p>Warning: RPCs made on this channel will prevent a shut-down transport from terminating. If
1419
     * you make long-running RPCs, you need to make sure they will finish in time after the
1420
     * Subchannel has transitioned away from {@code READY} state
1421
     * (notified through {@link #handleSubchannelState}).
1422
     *
1423
     * <p>Warning: this is INTERNAL API, is not supposed to be used by external users, and may
1424
     * change without notice. If you think you must use it, please file an issue.
1425
     */
1426
    @Internal
1427
    public Channel asChannel() {
1428
      throw new UnsupportedOperationException();
×
1429
    }
1430

1431
    /**
1432
     * Returns a {@link ChannelLogger} for this Subchannel.
1433
     *
1434
     * @since 1.17.0
1435
     */
1436
    public ChannelLogger getChannelLogger() {
1437
      throw new UnsupportedOperationException();
×
1438
    }
1439

1440
    /**
1441
     * Replaces the existing addresses used with this {@code Subchannel}. If the new and old
1442
     * addresses overlap, the Subchannel can continue using an existing connection.
1443
     *
1444
     * <p>It must be called from the Synchronization Context or will throw.
1445
     *
1446
     * @throws IllegalArgumentException if {@code addrs} is empty
1447
     * @since 1.22.0
1448
     */
1449
    public void updateAddresses(List<EquivalentAddressGroup> addrs) {
1450
      throw new UnsupportedOperationException();
×
1451
    }
1452

1453
    /**
1454
     * (Internal use only) returns an object that represents the underlying subchannel that is used
1455
     * by the Channel for sending RPCs when this {@link Subchannel} is picked.  This is an opaque
1456
     * object that is both provided and consumed by the Channel.  Its type <strong>is not</strong>
1457
     * {@code Subchannel}.
1458
     *
1459
     * <p>Warning: this is INTERNAL API, is not supposed to be used by external users, and may
1460
     * change without notice. If you think you must use it, please file an issue and we can consider
1461
     * removing its "internal" status.
1462
     */
1463
    @Internal
1464
    public Object getInternalSubchannel() {
1465
      throw new UnsupportedOperationException();
×
1466
    }
1467

1468
    /**
1469
     * (Internal use only) returns attributes of the address subchannel is connected to.
1470
     *
1471
     * <p>Warning: this is INTERNAL API, is not supposed to be used by external users, and may
1472
     * change without notice. If you think you must use it, please file an issue and we can consider
1473
     * removing its "internal" status.
1474
     */
1475
    @Internal
1476
    public Attributes getConnectedAddressAttributes() {
1477
      throw new UnsupportedOperationException();
×
1478
    }
1479
  }
1480

1481
  /**
1482
   * Receives state changes for one {@link Subchannel}. All methods are run under {@link
1483
   * Helper#getSynchronizationContext}.
1484
   *
1485
   * @since 1.22.0
1486
   */
1487
  public interface SubchannelStateListener {
1488
    /**
1489
     * Handles a state change on a Subchannel.
1490
     *
1491
     * <p>The initial state of a Subchannel is IDLE. You won't get a notification for the initial
1492
     * IDLE state.
1493
     *
1494
     * <p>If the new state is not SHUTDOWN, this method should create a new picker and call {@link
1495
     * Helper#updateBalancingState Helper.updateBalancingState()}.  Failing to do so may result in
1496
     * unnecessary delays of RPCs. Please refer to {@link PickResult#withSubchannel
1497
     * PickResult.withSubchannel()}'s javadoc for more information.
1498
     *
1499
     * <p>When a subchannel's state is IDLE or TRANSIENT_FAILURE and the address for the subchannel
1500
     * was received in {@link LoadBalancer#handleResolvedAddresses}, load balancers should call
1501
     * {@link Helper#refreshNameResolution} to inform polling name resolvers that it is an
1502
     * appropriate time to refresh the addresses. Without the refresh, changes to the addresses may
1503
     * never be detected.
1504
     *
1505
     * <p>SHUTDOWN can only happen in two cases.  One is that LoadBalancer called {@link
1506
     * Subchannel#shutdown} earlier, thus it should have already discarded this Subchannel.  The
1507
     * other is that Channel is doing a {@link ManagedChannel#shutdownNow forced shutdown} or has
1508
     * already terminated, thus there won't be further requests to LoadBalancer.  Therefore, the
1509
     * LoadBalancer usually don't need to react to a SHUTDOWN state.
1510
     *
1511
     * @param newState the new state
1512
     * @since 1.22.0
1513
     */
1514
    void onSubchannelState(ConnectivityStateInfo newState);
1515
  }
1516

1517
  /**
1518
   * Factory to create {@link LoadBalancer} instance.
1519
   *
1520
   * @since 1.2.0
1521
   */
1522
  @ThreadSafe
1523
  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
1524
  public abstract static class Factory {
1✔
1525
    /**
1526
     * Creates a {@link LoadBalancer} that will be used inside a channel.
1527
     *
1528
     * @since 1.2.0
1529
     */
1530
    public abstract LoadBalancer newLoadBalancer(Helper helper);
1531
  }
1532

1533
  /**
1534
   * A picker that always returns an erring pick.
1535
   *
1536
   * @deprecated Use {@code new FixedResultPicker(PickResult.withError(error))} instead.
1537
   */
1538
  @Deprecated
1539
  public static final class ErrorPicker extends SubchannelPicker {
1540

1541
    private final Status error;
1542

1543
    public ErrorPicker(Status error) {
×
1544
      this.error = checkNotNull(error, "error");
×
1545
    }
×
1546

1547
    @Override
1548
    public PickResult pickSubchannel(PickSubchannelArgs args) {
1549
      return PickResult.withError(error);
×
1550
    }
1551

1552
    @Override
1553
    public String toString() {
1554
      return MoreObjects.toStringHelper(this)
×
1555
          .add("error", error)
×
1556
          .toString();
×
1557
    }
1558
  }
1559

1560
  /** A picker that always returns the same result. */
1561
  public static final class FixedResultPicker extends SubchannelPicker {
1562
    private final PickResult result;
1563

1564
    public FixedResultPicker(PickResult result) {
1✔
1565
      this.result = Preconditions.checkNotNull(result, "result");
1✔
1566
    }
1✔
1567

1568
    @Override
1569
    public PickResult pickSubchannel(PickSubchannelArgs args) {
1570
      return result;
1✔
1571
    }
1572

1573
    @Override
1574
    public String toString() {
1575
      return "FixedResultPicker(" + result + ")";
1✔
1576
    }
1577

1578
    @Override
1579
    public int hashCode() {
1580
      return result.hashCode();
1✔
1581
    }
1582

1583
    @Override
1584
    public boolean equals(Object o) {
1585
      if (!(o instanceof FixedResultPicker)) {
1✔
1586
        return false;
1✔
1587
      }
1588
      FixedResultPicker that = (FixedResultPicker) o;
1✔
1589
      return this.result.equals(that.result);
1✔
1590
    }
1591
  }
1592
}
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