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

grpc / grpc-java / #20175

20 Feb 2026 07:37AM UTC coverage: 88.707% (+0.001%) from 88.706%
#20175

push

github

web-flow
unwrap ForwardingSubchannel during Picks (#12658)

This PR ensures that Load Balancing (LB) policies unwrap
`ForwardingSubchannel` instances before returning them in a
`PickResult`.

**Rationale:** Currently, the identity of a subchannel is "awkward"
because decorators break object identity. This forces the core channel
to use internal workarounds like `getInternalSubchannel()` to find the
underlying implementation. Removing these wrappers during the pick
process is a critical prerequisite for deleting Subchannel Attributes.

By enforcing unwrapping, `ManagedChannelImpl` can rely on the fact that
a returned subchannel is the same instance it originally created. This
allows the channel to use strongly-typed fields for state management
(via "blind casting") rather than abusing attributes to re-discover
information that should already be known. This also paves the way for
the eventual removal of the `getInternalSubchannel()` internal API.

**New APIs:** To ensure we don't "drop data on the floor" during the
unwrapping process, this PR adds two new non-static APIs to PickResult:
- copyWithSubchannel()
- copyWithStreamTracerFactory()

Unlike static factory methods, these instance methods follow a
"copy-and-update" pattern that preserves all existing pick-level
metadata (such as authority overrides or drop status) while only
swapping the specific field required.

35450 of 39963 relevant lines covered (88.71%)

0.89 hits per line

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

79.65
/../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
    // TODO(shivaspeaks): Need to deprecate old APIs and create new ones, 
636
    // per https://github.com/grpc/grpc-java/issues/12662.
637
    public static PickResult withSubchannel(
638
        Subchannel subchannel, @Nullable ClientStreamTracer.Factory streamTracerFactory) {
639
      return new PickResult(
1✔
640
          checkNotNull(subchannel, "subchannel"), streamTracerFactory, Status.OK,
1✔
641
          false);
642
    }
643

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

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

666
    /**
667
     * Creates a new {@code PickResult} with the given {@code subchannel},
668
     * but retains all other properties from this {@code PickResult}.
669
     *
670
     * @since 1.80.0
671
     */
672
    public PickResult copyWithSubchannel(Subchannel subchannel) {
673
      return new PickResult(checkNotNull(subchannel, "subchannel"), streamTracerFactory,
1✔
674
          status, drop, authorityOverride);
675
    }
676

677
    /**
678
     * Creates a new {@code PickResult} with the given {@code streamTracerFactory},
679
     * but retains all other properties from this {@code PickResult}.
680
     *
681
     * @since 1.80.0
682
     */
683
    public PickResult copyWithStreamTracerFactory(
684
        @Nullable ClientStreamTracer.Factory streamTracerFactory) {
685
      return new PickResult(subchannel, streamTracerFactory, status, drop, authorityOverride);
1✔
686
    }
687

688
    /**
689
     * A decision to report a connectivity error to the RPC.  If the RPC is {@link
690
     * CallOptions#withWaitForReady wait-for-ready}, it will stay buffered.  Otherwise, it will fail
691
     * with the given error.
692
     *
693
     * @param error the error status.  Must not be OK.
694
     * @since 1.2.0
695
     */
696
    public static PickResult withError(Status error) {
697
      Preconditions.checkArgument(!error.isOk(), "error status shouldn't be OK");
1✔
698
      return new PickResult(null, null, error, false);
1✔
699
    }
700

701
    /**
702
     * A decision to fail an RPC immediately.  This is a final decision and will ignore retry
703
     * policy.
704
     *
705
     * @param status the status with which the RPC will fail.  Must not be OK.
706
     * @since 1.8.0
707
     */
708
    public static PickResult withDrop(Status status) {
709
      Preconditions.checkArgument(!status.isOk(), "drop status shouldn't be OK");
1✔
710
      return new PickResult(null, null, status, true);
1✔
711
    }
712

713
    /**
714
     * No decision could be made.  The RPC will stay buffered.
715
     *
716
     * @since 1.2.0
717
     */
718
    public static PickResult withNoResult() {
719
      return NO_RESULT;
1✔
720
    }
721

722
    /** Returns the authority override if any. */
723
    @ExperimentalApi("https://github.com/grpc/grpc-java/issues/11656")
724
    @Nullable
725
    public String getAuthorityOverride() {
726
      return authorityOverride;
1✔
727
    }
728

729
    /**
730
     * The Subchannel if this result was created by {@link #withSubchannel withSubchannel()}, or
731
     * null otherwise.
732
     *
733
     * @since 1.2.0
734
     */
735
    @Nullable
736
    public Subchannel getSubchannel() {
737
      return subchannel;
1✔
738
    }
739

740
    /**
741
     * The stream tracer factory this result was created with.
742
     *
743
     * @since 1.3.0
744
     */
745
    @Nullable
746
    public ClientStreamTracer.Factory getStreamTracerFactory() {
747
      return streamTracerFactory;
1✔
748
    }
749

750
    /**
751
     * The status associated with this result.  Non-{@code OK} if created with {@link #withError
752
     * withError}, or {@code OK} otherwise.
753
     *
754
     * @since 1.2.0
755
     */
756
    public Status getStatus() {
757
      return status;
1✔
758
    }
759

760
    /**
761
     * Returns {@code true} if this result was created by {@link #withDrop withDrop()}.
762
     *
763
     * @since 1.8.0
764
     */
765
    public boolean isDrop() {
766
      return drop;
1✔
767
    }
768

769
    /**
770
     * Returns {@code true} if the pick was not created with {@link #withNoResult()}.
771
     */
772
    public boolean hasResult() {
773
      return !(subchannel == null && status.isOk());
1✔
774
    }
775

776
    @Override
777
    public String toString() {
778
      return MoreObjects.toStringHelper(this)
1✔
779
          .add("subchannel", subchannel)
1✔
780
          .add("streamTracerFactory", streamTracerFactory)
1✔
781
          .add("status", status)
1✔
782
          .add("drop", drop)
1✔
783
          .add("authority-override", authorityOverride)
1✔
784
          .toString();
1✔
785
    }
786

787
    @Override
788
    public int hashCode() {
789
      return Objects.hashCode(subchannel, status, streamTracerFactory, drop);
1✔
790
    }
791

792
    /**
793
     * Returns true if the {@link Subchannel}, {@link Status}, and
794
     * {@link ClientStreamTracer.Factory} all match.
795
     */
796
    @Override
797
    public boolean equals(Object other) {
798
      if (!(other instanceof PickResult)) {
1✔
799
        return false;
×
800
      }
801
      PickResult that = (PickResult) other;
1✔
802
      return Objects.equal(subchannel, that.subchannel) && Objects.equal(status, that.status)
1✔
803
          && Objects.equal(streamTracerFactory, that.streamTracerFactory)
1✔
804
          && drop == that.drop;
805
    }
806
  }
807

808
  /**
809
   * Arguments for creating a {@link Subchannel}.
810
   *
811
   * @since 1.22.0
812
   */
813
  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
814
  public static final class CreateSubchannelArgs {
815
    private final List<EquivalentAddressGroup> addrs;
816
    private final Attributes attrs;
817
    private final Object[][] customOptions;
818

819
    private CreateSubchannelArgs(
820
        List<EquivalentAddressGroup> addrs, Attributes attrs, Object[][] customOptions) {
1✔
821
      this.addrs = checkNotNull(addrs, "addresses are not set");
1✔
822
      this.attrs = checkNotNull(attrs, "attrs");
1✔
823
      this.customOptions = checkNotNull(customOptions, "customOptions");
1✔
824
    }
1✔
825

826
    /**
827
     * Returns the addresses, which is an unmodifiable list.
828
     */
829
    public List<EquivalentAddressGroup> getAddresses() {
830
      return addrs;
1✔
831
    }
832

833
    /**
834
     * Returns the attributes.
835
     */
836
    public Attributes getAttributes() {
837
      return attrs;
1✔
838
    }
839

840
    /**
841
     * Get the value for a custom option or its inherent default.
842
     *
843
     * @param key Key identifying option
844
     */
845
    @SuppressWarnings("unchecked")
846
    public <T> T getOption(Key<T> key) {
847
      Preconditions.checkNotNull(key, "key");
1✔
848
      for (int i = 0; i < customOptions.length; i++) {
1✔
849
        if (key.equals(customOptions[i][0])) {
1✔
850
          return (T) customOptions[i][1];
1✔
851
        }
852
      }
853
      return key.defaultValue;
1✔
854
    }
855

856
    /**
857
     * Returns a builder with the same initial values as this object.
858
     */
859
    public Builder toBuilder() {
860
      return newBuilder().setAddresses(addrs).setAttributes(attrs).copyCustomOptions(customOptions);
1✔
861
    }
862

863
    /**
864
     * Creates a new builder.
865
     */
866
    public static Builder newBuilder() {
867
      return new Builder();
1✔
868
    }
869

870
    @Override
871
    public String toString() {
872
      return MoreObjects.toStringHelper(this)
1✔
873
          .add("addrs", addrs)
1✔
874
          .add("attrs", attrs)
1✔
875
          .add("customOptions", Arrays.deepToString(customOptions))
1✔
876
          .toString();
1✔
877
    }
878

879
    @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
880
    public static final class Builder {
881

882
      private static final Object[][] EMPTY_CUSTOM_OPTIONS = new Object[0][2];
1✔
883

884
      private List<EquivalentAddressGroup> addrs;
885
      private Attributes attrs = Attributes.EMPTY;
1✔
886
      private Object[][] customOptions = EMPTY_CUSTOM_OPTIONS;
1✔
887

888
      Builder() {
1✔
889
      }
1✔
890

891
      private Builder copyCustomOptions(Object[][] options) {
892
        customOptions = new Object[options.length][2];
1✔
893
        System.arraycopy(options, 0, customOptions, 0, options.length);
1✔
894
        return this;
1✔
895
      }
896

897
      /**
898
       * Add a custom option. Any existing value for the key is overwritten.
899
       *
900
       * <p>This is an <strong>optional</strong> property.
901
       *
902
       * @param key the option key
903
       * @param value the option value
904
       */
905
      public <T> Builder addOption(Key<T> key, T value) {
906
        Preconditions.checkNotNull(key, "key");
1✔
907
        Preconditions.checkNotNull(value, "value");
1✔
908

909
        int existingIdx = -1;
1✔
910
        for (int i = 0; i < customOptions.length; i++) {
1✔
911
          if (key.equals(customOptions[i][0])) {
1✔
912
            existingIdx = i;
1✔
913
            break;
1✔
914
          }
915
        }
916

917
        if (existingIdx == -1) {
1✔
918
          Object[][] newCustomOptions = new Object[customOptions.length + 1][2];
1✔
919
          System.arraycopy(customOptions, 0, newCustomOptions, 0, customOptions.length);
1✔
920
          customOptions = newCustomOptions;
1✔
921
          existingIdx = customOptions.length - 1;
1✔
922
        }
923
        customOptions[existingIdx] = new Object[]{key, value};
1✔
924
        return this;
1✔
925
      }
926

927
      /**
928
       * The addresses to connect to.  All addresses are considered equivalent and will be tried
929
       * in the order they are provided.
930
       */
931
      public Builder setAddresses(EquivalentAddressGroup addrs) {
932
        this.addrs = Collections.singletonList(addrs);
1✔
933
        return this;
1✔
934
      }
935

936
      /**
937
       * The addresses to connect to.  All addresses are considered equivalent and will
938
       * be tried in the order they are provided.
939
       *
940
       * <p>This is a <strong>required</strong> property.
941
       *
942
       * @throws IllegalArgumentException if {@code addrs} is empty
943
       */
944
      public Builder setAddresses(List<EquivalentAddressGroup> addrs) {
945
        checkArgument(!addrs.isEmpty(), "addrs is empty");
1✔
946
        this.addrs = Collections.unmodifiableList(new ArrayList<>(addrs));
1✔
947
        return this;
1✔
948
      }
949

950
      /**
951
       * Attributes provided here will be included in {@link Subchannel#getAttributes}.
952
       *
953
       * <p>This is an <strong>optional</strong> property.  Default is empty if not set.
954
       */
955
      public Builder setAttributes(Attributes attrs) {
956
        this.attrs = checkNotNull(attrs, "attrs");
1✔
957
        return this;
1✔
958
      }
959

960
      /**
961
       * Creates a new args object.
962
       */
963
      public CreateSubchannelArgs build() {
964
        return new CreateSubchannelArgs(addrs, attrs, customOptions);
1✔
965
      }
966
    }
967

968
    /**
969
     * Key for a key-value pair. Uses reference equality.
970
     */
971
    @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
972
    public static final class Key<T> {
973

974
      private final String debugString;
975
      private final T defaultValue;
976

977
      private Key(String debugString, T defaultValue) {
1✔
978
        this.debugString = debugString;
1✔
979
        this.defaultValue = defaultValue;
1✔
980
      }
1✔
981

982
      /**
983
       * Factory method for creating instances of {@link Key}. The default value of the key is
984
       * {@code null}.
985
       *
986
       * @param debugString a debug string that describes this key.
987
       * @param <T> Key type
988
       * @return Key object
989
       */
990
      public static <T> Key<T> create(String debugString) {
991
        Preconditions.checkNotNull(debugString, "debugString");
1✔
992
        return new Key<>(debugString, /*defaultValue=*/ null);
1✔
993
      }
994

995
      /**
996
       * Factory method for creating instances of {@link Key}.
997
       *
998
       * @param debugString a debug string that describes this key.
999
       * @param defaultValue default value to return when value for key not set
1000
       * @param <T> Key type
1001
       * @return Key object
1002
       */
1003
      public static <T> Key<T> createWithDefault(String debugString, T defaultValue) {
1004
        Preconditions.checkNotNull(debugString, "debugString");
1✔
1005
        return new Key<>(debugString, defaultValue);
1✔
1006
      }
1007

1008
      /**
1009
       * Returns the user supplied default value for this key.
1010
       */
1011
      public T getDefault() {
1012
        return defaultValue;
×
1013
      }
1014

1015
      @Override
1016
      public String toString() {
1017
        return debugString;
1✔
1018
      }
1019
    }
1020
  }
1021

1022
  /**
1023
   * Provides essentials for LoadBalancer implementations.
1024
   *
1025
   * @since 1.2.0
1026
   */
1027
  @ThreadSafe
1028
  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
1029
  public abstract static class Helper {
1✔
1030
    /**
1031
     * Creates a Subchannel, which is a logical connection to the given group of addresses which are
1032
     * considered equivalent.  The {@code attrs} are custom attributes associated with this
1033
     * Subchannel, and can be accessed later through {@link Subchannel#getAttributes
1034
     * Subchannel.getAttributes()}.
1035
     *
1036
     * <p>The LoadBalancer is responsible for closing unused Subchannels, and closing all
1037
     * Subchannels within {@link #shutdown}.
1038
     *
1039
     * <p>It must be called from {@link #getSynchronizationContext the Synchronization Context}
1040
     *
1041
     * @return Must return a valid Subchannel object, may not return null.
1042
     *
1043
     * @since 1.22.0
1044
     */
1045
    public Subchannel createSubchannel(CreateSubchannelArgs args) {
1046
      throw new UnsupportedOperationException();
1✔
1047
    }
1048

1049
    /**
1050
     * Create an out-of-band channel for the LoadBalancer’s own RPC needs, e.g., talking to an
1051
     * external load-balancer service.
1052
     *
1053
     * <p>The LoadBalancer is responsible for closing unused OOB channels, and closing all OOB
1054
     * channels within {@link #shutdown}.
1055
     *
1056
     * @since 1.4.0
1057
     */
1058
    public abstract ManagedChannel createOobChannel(EquivalentAddressGroup eag, String authority);
1059

1060
    /**
1061
     * Create an out-of-band channel for the LoadBalancer's own RPC needs, e.g., talking to an
1062
     * external load-balancer service. This version of the method allows multiple EAGs, so different
1063
     * addresses can have different authorities.
1064
     *
1065
     * <p>The LoadBalancer is responsible for closing unused OOB channels, and closing all OOB
1066
     * channels within {@link #shutdown}.
1067
     * */
1068
    public ManagedChannel createOobChannel(List<EquivalentAddressGroup> eag,
1069
        String authority) {
1070
      throw new UnsupportedOperationException();
×
1071
    }
1072

1073
    /**
1074
     * Updates the addresses used for connections in the {@code Channel} that was created by {@link
1075
     * #createOobChannel(EquivalentAddressGroup, String)}. This is superior to {@link
1076
     * #createOobChannel(EquivalentAddressGroup, String)} when the old and new addresses overlap,
1077
     * since the channel can continue using an existing connection.
1078
     *
1079
     * @throws IllegalArgumentException if {@code channel} was not returned from {@link
1080
     *     #createOobChannel}
1081
     * @since 1.4.0
1082
     */
1083
    public void updateOobChannelAddresses(ManagedChannel channel, EquivalentAddressGroup eag) {
1084
      throw new UnsupportedOperationException();
×
1085
    }
1086

1087
    /**
1088
     * Updates the addresses with a new EAG list. Connection is continued when old and new addresses
1089
     * overlap.
1090
     * */
1091
    public void updateOobChannelAddresses(ManagedChannel channel,
1092
        List<EquivalentAddressGroup> eag) {
1093
      throw new UnsupportedOperationException();
×
1094
    }
1095

1096
    /**
1097
     * Creates an out-of-band channel for LoadBalancer's own RPC needs, e.g., talking to an external
1098
     * load-balancer service, that is specified by a target string.  See the documentation on
1099
     * {@link ManagedChannelBuilder#forTarget} for the format of a target string.
1100
     *
1101
     * <p>The target string will be resolved by a {@link NameResolver} created according to the
1102
     * target string.
1103
     *
1104
     * <p>The LoadBalancer is responsible for closing unused OOB channels, and closing all OOB
1105
     * channels within {@link #shutdown}.
1106
     *
1107
     * @since 1.20.0
1108
     */
1109
    public ManagedChannel createResolvingOobChannel(String target) {
1110
      return createResolvingOobChannelBuilder(target).build();
1✔
1111
    }
1112

1113
    /**
1114
     * Creates an out-of-band channel builder for LoadBalancer's own RPC needs, e.g., talking to an
1115
     * external load-balancer service, that is specified by a target string.  See the documentation
1116
     * on {@link ManagedChannelBuilder#forTarget} for the format of a target string.
1117
     *
1118
     * <p>The target string will be resolved by a {@link NameResolver} created according to the
1119
     * target string.
1120
     *
1121
     * <p>The returned oob-channel builder defaults to use the same authority and ChannelCredentials
1122
     * (without bearer tokens) as the parent channel's for authentication. This is different from
1123
     * {@link #createResolvingOobChannelBuilder(String, ChannelCredentials)}.
1124
     *
1125
     * <p>The LoadBalancer is responsible for closing unused OOB channels, and closing all OOB
1126
     * channels within {@link #shutdown}.
1127
     *
1128
     * @deprecated Use {@link #createResolvingOobChannelBuilder(String, ChannelCredentials)}
1129
     *     instead.
1130
     * @since 1.31.0
1131
     */
1132
    @Deprecated
1133
    public ManagedChannelBuilder<?> createResolvingOobChannelBuilder(String target) {
1134
      throw new UnsupportedOperationException("Not implemented");
×
1135
    }
1136

1137
    /**
1138
     * Creates an out-of-band channel builder for LoadBalancer's own RPC needs, e.g., talking to an
1139
     * external load-balancer service, that is specified by a target string and credentials.  See
1140
     * the documentation on {@link Grpc#newChannelBuilder} for the format of a target string.
1141
     *
1142
     * <p>The target string will be resolved by a {@link NameResolver} created according to the
1143
     * target string.
1144
     *
1145
     * <p>The LoadBalancer is responsible for closing unused OOB channels, and closing all OOB
1146
     * channels within {@link #shutdown}.
1147
     *
1148
     * @since 1.35.0
1149
     */
1150
    public ManagedChannelBuilder<?> createResolvingOobChannelBuilder(
1151
        String target, ChannelCredentials creds) {
1152
      throw new UnsupportedOperationException();
×
1153
    }
1154

1155
    /**
1156
     * Set a new state with a new picker to the channel.
1157
     *
1158
     * <p>When a new picker is provided via {@code updateBalancingState()}, the channel will apply
1159
     * the picker on all buffered RPCs, by calling {@link SubchannelPicker#pickSubchannel(
1160
     * LoadBalancer.PickSubchannelArgs)}.
1161
     *
1162
     * <p>The channel will hold the picker and use it for all RPCs, until {@code
1163
     * updateBalancingState()} is called again and a new picker replaces the old one.  If {@code
1164
     * updateBalancingState()} has never been called, the channel will buffer all RPCs until a
1165
     * picker is provided.
1166
     *
1167
     * <p>It should be called from the Synchronization Context.  Currently will log a warning if
1168
     * violated.  It will become an exception eventually.  See <a
1169
     * href="https://github.com/grpc/grpc-java/issues/5015">#5015</a> for the background.
1170
     *
1171
     * <p>The passed state will be the channel's new state. The SHUTDOWN state should not be passed
1172
     * and its behavior is undefined.
1173
     *
1174
     * @since 1.6.0
1175
     */
1176
    public abstract void updateBalancingState(
1177
        @Nonnull ConnectivityState newState, @Nonnull SubchannelPicker newPicker);
1178

1179
    /**
1180
     * Call {@link NameResolver#refresh} on the channel's resolver.
1181
     *
1182
     * <p>It should be called from the Synchronization Context.  Currently will log a warning if
1183
     * violated.  It will become an exception eventually.  See <a
1184
     * href="https://github.com/grpc/grpc-java/issues/5015">#5015</a> for the background.
1185
     *
1186
     * @since 1.18.0
1187
     */
1188
    public void refreshNameResolution() {
1189
      throw new UnsupportedOperationException();
×
1190
    }
1191

1192
    /**
1193
     * Historically the channel automatically refreshes name resolution if any subchannel
1194
     * connection is broken. It's transitioning to let load balancers make the decision. To
1195
     * avoid silent breakages, the channel checks if {@link #refreshNameResolution} is called
1196
     * by the load balancer. If not, it will do it and log a warning. This will be removed in
1197
     * the future and load balancers are completely responsible for triggering the refresh.
1198
     * See <a href="https://github.com/grpc/grpc-java/issues/8088">#8088</a> for the background.
1199
     *
1200
     * <p>This should rarely be used, but sometimes the address for the subchannel wasn't
1201
     * provided by the name resolver and a refresh needs to be directed somewhere else instead.
1202
     * Then you can call this method to disable the short-tem check for detecting LoadBalancers
1203
     * that need to be updated for the new expected behavior.
1204
     *
1205
     * @since 1.38.0
1206
     * @deprecated Warning has been removed
1207
     */
1208
    @ExperimentalApi("https://github.com/grpc/grpc-java/issues/8088")
1209
    @Deprecated
1210
    public void ignoreRefreshNameResolutionCheck() {
1211
      // no-op
1212
    }
×
1213

1214
    /**
1215
     * Returns a {@link SynchronizationContext} that runs tasks in the same Synchronization Context
1216
     * as that the callback methods on the {@link LoadBalancer} interface are run in.
1217
     *
1218
     * <p>Work added to the synchronization context might not run immediately, so LB implementations
1219
     * must be careful to ensure that any assumptions still hold when it is executed. In particular,
1220
     * the LB might have been shut down or subchannels might have changed state.
1221
     *
1222
     * <p>Pro-tip: in order to call {@link SynchronizationContext#schedule}, you need to provide a
1223
     * {@link ScheduledExecutorService}.  {@link #getScheduledExecutorService} is provided for your
1224
     * convenience.
1225
     *
1226
     * @since 1.17.0
1227
     */
1228
    public SynchronizationContext getSynchronizationContext() {
1229
      // TODO(zhangkun): make getSynchronizationContext() abstract after runSerialized() is deleted
1230
      throw new UnsupportedOperationException();
×
1231
    }
1232

1233
    /**
1234
     * Returns a {@link ScheduledExecutorService} for scheduling delayed tasks.
1235
     *
1236
     * <p>This service is a shared resource and is only meant for quick tasks.  DO NOT block or run
1237
     * time-consuming tasks.
1238
     *
1239
     * <p>The returned service doesn't support {@link ScheduledExecutorService#shutdown shutdown()}
1240
     * and {@link ScheduledExecutorService#shutdownNow shutdownNow()}.  They will throw if called.
1241
     *
1242
     * @since 1.17.0
1243
     */
1244
    public ScheduledExecutorService getScheduledExecutorService() {
1245
      throw new UnsupportedOperationException();
×
1246
    }
1247

1248
    /**
1249
     * Returns the authority string of the channel, which is derived from the DNS-style target name.
1250
     * If overridden by a load balancer, {@link #getUnsafeChannelCredentials} must also be
1251
     * overridden to call {@link #getChannelCredentials} or provide appropriate credentials.
1252
     *
1253
     * @since 1.2.0
1254
     */
1255
    public abstract String getAuthority();
1256

1257
    /**
1258
     * Returns the target string of the channel, guaranteed to include its scheme.
1259
     */
1260
    public String getChannelTarget() {
1261
      throw new UnsupportedOperationException();
×
1262
    }
1263

1264
    /**
1265
     * Returns the ChannelCredentials used to construct the channel, without bearer tokens.
1266
     *
1267
     * @since 1.35.0
1268
     */
1269
    public ChannelCredentials getChannelCredentials() {
1270
      return getUnsafeChannelCredentials().withoutBearerTokens();
×
1271
    }
1272

1273
    /**
1274
     * Returns the UNSAFE ChannelCredentials used to construct the channel,
1275
     * including bearer tokens. Load balancers should generally have no use for
1276
     * these credentials and use of them is heavily discouraged. These must be used
1277
     * <em>very</em> carefully to avoid sending bearer tokens to untrusted servers
1278
     * as the server could then impersonate the client. Generally it is only safe
1279
     * to use these credentials when communicating with the backend.
1280
     *
1281
     * @since 1.35.0
1282
     */
1283
    public ChannelCredentials getUnsafeChannelCredentials() {
1284
      throw new UnsupportedOperationException();
×
1285
    }
1286

1287
    /**
1288
     * Returns the {@link ChannelLogger} for the Channel served by this LoadBalancer.
1289
     *
1290
     * @since 1.17.0
1291
     */
1292
    public ChannelLogger getChannelLogger() {
1293
      throw new UnsupportedOperationException();
×
1294
    }
1295

1296
    /**
1297
     * Returns the {@link NameResolver.Args} that the Channel uses to create {@link NameResolver}s.
1298
     *
1299
     * @since 1.22.0
1300
     */
1301
    public NameResolver.Args getNameResolverArgs() {
1302
      throw new UnsupportedOperationException();
×
1303
    }
1304

1305
    /**
1306
     * Returns the {@link NameResolverRegistry} that the Channel uses to look for {@link
1307
     * NameResolver}s.
1308
     *
1309
     * @since 1.22.0
1310
     */
1311
    public NameResolverRegistry getNameResolverRegistry() {
1312
      throw new UnsupportedOperationException();
×
1313
    }
1314

1315
    /**
1316
     * Returns the {@link MetricRecorder} that the channel uses to record metrics.
1317
     *
1318
     * @since 1.64.0
1319
     */
1320
    @Internal
1321
    public MetricRecorder getMetricRecorder() {
1322
      return new MetricRecorder() {};
×
1323
    }
1324
  }
1325

1326
  /**
1327
   * A logical connection to a server, or a group of equivalent servers represented by an {@link 
1328
   * EquivalentAddressGroup}.
1329
   *
1330
   * <p>It maintains at most one physical connection (aka transport) for sending new RPCs, while
1331
   * also keeps track of previous transports that has been shut down but not terminated yet.
1332
   *
1333
   * <p>If there isn't an active transport yet, and an RPC is assigned to the Subchannel, it will
1334
   * create a new transport.  It won't actively create transports otherwise.  {@link
1335
   * #requestConnection requestConnection()} can be used to ask Subchannel to create a transport if
1336
   * there isn't any.
1337
   *
1338
   * <p>{@link #start} must be called prior to calling any other methods, with the exception of
1339
   * {@link #shutdown}, which can be called at any time.
1340
   *
1341
   * @since 1.2.0
1342
   */
1343
  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
1344
  public abstract static class Subchannel {
1✔
1345
    /**
1346
     * Starts the Subchannel.  Can only be called once.
1347
     *
1348
     * <p>Must be called prior to any other method on this class, except for {@link #shutdown} which
1349
     * may be called at any time.
1350
     *
1351
     * <p>Must be called from the {@link Helper#getSynchronizationContext Synchronization Context},
1352
     * otherwise it may throw.  See <a href="https://github.com/grpc/grpc-java/issues/5015">
1353
     * #5015</a> for more discussions.
1354
     *
1355
     * @param listener receives state updates for this Subchannel.
1356
     */
1357
    public void start(SubchannelStateListener listener) {
1358
      throw new UnsupportedOperationException("Not implemented");
×
1359
    }
1360

1361
    /**
1362
     * Shuts down the Subchannel.  After this method is called, this Subchannel should no longer
1363
     * be returned by the latest {@link SubchannelPicker picker}, and can be safely discarded.
1364
     *
1365
     * <p>Calling it on an already shut-down Subchannel has no effect.
1366
     *
1367
     * <p>It should be called from the Synchronization Context.  Currently will log a warning if
1368
     * violated.  It will become an exception eventually.  See <a
1369
     * href="https://github.com/grpc/grpc-java/issues/5015">#5015</a> for the background.
1370
     *
1371
     * @since 1.2.0
1372
     */
1373
    public abstract void shutdown();
1374

1375
    /**
1376
     * Asks the Subchannel to create a connection (aka transport), if there isn't an active one.
1377
     *
1378
     * <p>It should be called from the Synchronization Context.  Currently will log a warning if
1379
     * violated.  It will become an exception eventually.  See <a
1380
     * href="https://github.com/grpc/grpc-java/issues/5015">#5015</a> for the background.
1381
     *
1382
     * @since 1.2.0
1383
     */
1384
    public abstract void requestConnection();
1385

1386
    /**
1387
     * Returns the addresses that this Subchannel is bound to.  This can be called only if
1388
     * the Subchannel has only one {@link EquivalentAddressGroup}.  Under the hood it calls
1389
     * {@link #getAllAddresses}.
1390
     *
1391
     * <p>It should be called from the Synchronization Context.  Currently will log a warning if
1392
     * violated.  It will become an exception eventually.  See <a
1393
     * href="https://github.com/grpc/grpc-java/issues/5015">#5015</a> for the background.
1394
     *
1395
     * @throws IllegalStateException if this subchannel has more than one EquivalentAddressGroup.
1396
     *         Use {@link #getAllAddresses} instead
1397
     * @since 1.2.0
1398
     */
1399
    public final EquivalentAddressGroup getAddresses() {
1400
      List<EquivalentAddressGroup> groups = getAllAddresses();
1✔
1401
      Preconditions.checkState(groups != null && groups.size() == 1,
1✔
1402
          "%s does not have exactly one group", groups);
1403
      return groups.get(0);
1✔
1404
    }
1405

1406
    /**
1407
     * Returns the addresses that this Subchannel is bound to. The returned list will not be empty.
1408
     *
1409
     * <p>It should be called from the Synchronization Context.  Currently will log a warning if
1410
     * violated.  It will become an exception eventually.  See <a
1411
     * href="https://github.com/grpc/grpc-java/issues/5015">#5015</a> for the background.
1412
     *
1413
     * @since 1.14.0
1414
     */
1415
    public List<EquivalentAddressGroup> getAllAddresses() {
1416
      throw new UnsupportedOperationException();
×
1417
    }
1418

1419
    /**
1420
     * The same attributes passed to {@link Helper#createSubchannel Helper.createSubchannel()}.
1421
     * LoadBalancer can use it to attach additional information here, e.g., the shard this
1422
     * Subchannel belongs to.
1423
     *
1424
     * @since 1.2.0
1425
     */
1426
    public abstract Attributes getAttributes();
1427

1428
    /**
1429
     * (Internal use only) returns a {@link Channel} that is backed by this Subchannel.  This allows
1430
     * a LoadBalancer to issue its own RPCs for auxiliary purposes, such as health-checking, on
1431
     * already-established connections.  This channel has certain restrictions:
1432
     * <ol>
1433
     *   <li>It can issue RPCs only if the Subchannel is {@code READY}. If {@link
1434
     *   Channel#newCall} is called when the Subchannel is not {@code READY}, the RPC will fail
1435
     *   immediately.</li>
1436
     *   <li>It doesn't support {@link CallOptions#withWaitForReady wait-for-ready} RPCs. Such RPCs
1437
     *   will fail immediately.</li>
1438
     * </ol>
1439
     *
1440
     * <p>RPCs made on this Channel is not counted when determining ManagedChannel's {@link
1441
     * ManagedChannelBuilder#idleTimeout idle mode}.  In other words, they won't prevent
1442
     * ManagedChannel from entering idle mode.
1443
     *
1444
     * <p>Warning: RPCs made on this channel will prevent a shut-down transport from terminating. If
1445
     * you make long-running RPCs, you need to make sure they will finish in time after the
1446
     * Subchannel has transitioned away from {@code READY} state
1447
     * (notified through {@link #handleSubchannelState}).
1448
     *
1449
     * <p>Warning: this is INTERNAL API, is not supposed to be used by external users, and may
1450
     * change without notice. If you think you must use it, please file an issue.
1451
     */
1452
    @Internal
1453
    public Channel asChannel() {
1454
      throw new UnsupportedOperationException();
×
1455
    }
1456

1457
    /**
1458
     * Returns a {@link ChannelLogger} for this Subchannel.
1459
     *
1460
     * @since 1.17.0
1461
     */
1462
    public ChannelLogger getChannelLogger() {
1463
      throw new UnsupportedOperationException();
×
1464
    }
1465

1466
    /**
1467
     * Replaces the existing addresses used with this {@code Subchannel}. If the new and old
1468
     * addresses overlap, the Subchannel can continue using an existing connection.
1469
     *
1470
     * <p>It must be called from the Synchronization Context or will throw.
1471
     *
1472
     * @throws IllegalArgumentException if {@code addrs} is empty
1473
     * @since 1.22.0
1474
     */
1475
    public void updateAddresses(List<EquivalentAddressGroup> addrs) {
1476
      throw new UnsupportedOperationException();
×
1477
    }
1478

1479
    /**
1480
     * (Internal use only) returns an object that represents the underlying subchannel that is used
1481
     * by the Channel for sending RPCs when this {@link Subchannel} is picked.  This is an opaque
1482
     * object that is both provided and consumed by the Channel.  Its type <strong>is not</strong>
1483
     * {@code Subchannel}.
1484
     *
1485
     * <p>Warning: this is INTERNAL API, is not supposed to be used by external users, and may
1486
     * change without notice. If you think you must use it, please file an issue and we can consider
1487
     * removing its "internal" status.
1488
     */
1489
    @Internal
1490
    public Object getInternalSubchannel() {
1491
      throw new UnsupportedOperationException();
×
1492
    }
1493

1494
    /**
1495
     * (Internal use only) returns attributes of the address subchannel is connected to.
1496
     *
1497
     * <p>Warning: this is INTERNAL API, is not supposed to be used by external users, and may
1498
     * change without notice. If you think you must use it, please file an issue and we can consider
1499
     * removing its "internal" status.
1500
     */
1501
    @Internal
1502
    public Attributes getConnectedAddressAttributes() {
1503
      throw new UnsupportedOperationException();
×
1504
    }
1505
  }
1506

1507
  /**
1508
   * Receives state changes for one {@link Subchannel}. All methods are run under {@link
1509
   * Helper#getSynchronizationContext}.
1510
   *
1511
   * @since 1.22.0
1512
   */
1513
  public interface SubchannelStateListener {
1514
    /**
1515
     * Handles a state change on a Subchannel.
1516
     *
1517
     * <p>The initial state of a Subchannel is IDLE. You won't get a notification for the initial
1518
     * IDLE state.
1519
     *
1520
     * <p>If the new state is not SHUTDOWN, this method should create a new picker and call {@link
1521
     * Helper#updateBalancingState Helper.updateBalancingState()}.  Failing to do so may result in
1522
     * unnecessary delays of RPCs. Please refer to {@link PickResult#withSubchannel
1523
     * PickResult.withSubchannel()}'s javadoc for more information.
1524
     *
1525
     * <p>When a subchannel's state is IDLE or TRANSIENT_FAILURE and the address for the subchannel
1526
     * was received in {@link LoadBalancer#handleResolvedAddresses}, load balancers should call
1527
     * {@link Helper#refreshNameResolution} to inform polling name resolvers that it is an
1528
     * appropriate time to refresh the addresses. Without the refresh, changes to the addresses may
1529
     * never be detected.
1530
     *
1531
     * <p>SHUTDOWN can only happen in two cases.  One is that LoadBalancer called {@link
1532
     * Subchannel#shutdown} earlier, thus it should have already discarded this Subchannel.  The
1533
     * other is that Channel is doing a {@link ManagedChannel#shutdownNow forced shutdown} or has
1534
     * already terminated, thus there won't be further requests to LoadBalancer.  Therefore, the
1535
     * LoadBalancer usually don't need to react to a SHUTDOWN state.
1536
     *
1537
     * @param newState the new state
1538
     * @since 1.22.0
1539
     */
1540
    void onSubchannelState(ConnectivityStateInfo newState);
1541
  }
1542

1543
  /**
1544
   * Factory to create {@link LoadBalancer} instance.
1545
   *
1546
   * @since 1.2.0
1547
   */
1548
  @ThreadSafe
1549
  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
1550
  public abstract static class Factory {
1✔
1551
    /**
1552
     * Creates a {@link LoadBalancer} that will be used inside a channel.
1553
     *
1554
     * @since 1.2.0
1555
     */
1556
    public abstract LoadBalancer newLoadBalancer(Helper helper);
1557
  }
1558

1559
  /**
1560
   * A picker that always returns an erring pick.
1561
   *
1562
   * @deprecated Use {@code new FixedResultPicker(PickResult.withError(error))} instead.
1563
   */
1564
  @Deprecated
1565
  public static final class ErrorPicker extends SubchannelPicker {
1566

1567
    private final Status error;
1568

1569
    public ErrorPicker(Status error) {
×
1570
      this.error = checkNotNull(error, "error");
×
1571
    }
×
1572

1573
    @Override
1574
    public PickResult pickSubchannel(PickSubchannelArgs args) {
1575
      return PickResult.withError(error);
×
1576
    }
1577

1578
    @Override
1579
    public String toString() {
1580
      return MoreObjects.toStringHelper(this)
×
1581
          .add("error", error)
×
1582
          .toString();
×
1583
    }
1584
  }
1585

1586
  /** A picker that always returns the same result. */
1587
  public static final class FixedResultPicker extends SubchannelPicker {
1588
    private final PickResult result;
1589

1590
    public FixedResultPicker(PickResult result) {
1✔
1591
      this.result = Preconditions.checkNotNull(result, "result");
1✔
1592
    }
1✔
1593

1594
    @Override
1595
    public PickResult pickSubchannel(PickSubchannelArgs args) {
1596
      return result;
1✔
1597
    }
1598

1599
    @Override
1600
    public String toString() {
1601
      return "FixedResultPicker(" + result + ")";
1✔
1602
    }
1603

1604
    @Override
1605
    public int hashCode() {
1606
      return result.hashCode();
1✔
1607
    }
1608

1609
    @Override
1610
    public boolean equals(Object o) {
1611
      if (!(o instanceof FixedResultPicker)) {
1✔
1612
        return false;
1✔
1613
      }
1614
      FixedResultPicker that = (FixedResultPicker) o;
1✔
1615
      return this.result.equals(that.result);
1✔
1616
    }
1617
  }
1618
}
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