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

grpc / grpc-java / #20494

30 Sep 2026 08:29AM UTC coverage: 89.351% (+0.05%) from 89.306%
#20494

push

github

web-flow
core: Implement [A121](https://github.com/grpc/proposal/pull/556) (#12893)

39251 of 43929 relevant lines covered (89.35%)

0.89 hits per line

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

80.0
/../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

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

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

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

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

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

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

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

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

155
  private int recursionCount;
156

157
  /**
158
   * Handles newly resolved addresses and metadata attributes from name resolution system.
159
   * Addresses in {@link EquivalentAddressGroup} should be considered equivalent but may be
160
   * flattened into a single list if needed.
161
   *
162
   * @param resolvedAddresses the resolved server addresses, attributes, and config.
163
   * @since 1.21.0
164
   *
165
   * @deprecated  Use instead {@link #acceptResolvedAddresses(ResolvedAddresses)}
166
   */
167
  @Deprecated
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
   * @param resolvedAddresses the resolved server addresses, attributes, and config
183
   * @return {@code Status.OK} if the resolved addresses were accepted, otherwise an error to report
184
   *     to the name resolver
185
   *
186
   * @since 1.49.0
187
   */
188
  public Status acceptResolvedAddresses(ResolvedAddresses resolvedAddresses) {
189
    if (resolvedAddresses.getAddresses().isEmpty()
1 ✔
190
        && !canHandleEmptyAddressListFromNameResolution()) {
×
191
      Status unavailableStatus = Status.UNAVAILABLE.withDescription(
×
192
              "NameResolver returned no usable address. addrs=" + resolvedAddresses.getAddresses()
×
193
                      + ", attrs=" + resolvedAddresses.getAttributes());
×
194
      handleNameResolutionError(unavailableStatus);
×
195
      return unavailableStatus;
×
196
    } else {
197
      if (recursionCount++ == 0) {
1 ✔
198
        handleResolvedAddresses(resolvedAddresses);
×
199
      }
200
      recursionCount = 0;
1 ✔
201

202
      return Status.OK;
1 ✔
203
    }
204
  }
205

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

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

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

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

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

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

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

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

295
      Builder() {}
1 ✔
296

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

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

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

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

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

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

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

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

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

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

410
  /**
411
   * Whether this LoadBalancer can handle empty address group list to be passed to {@link
412
   * #handleResolvedAddresses(ResolvedAddresses)}.  The default implementation returns
413
   * {@code false}, meaning that if the NameResolver returns an empty list, the Channel will turn
414
   * that into an error and call {@link #handleNameResolutionError}.  LoadBalancers that want to
415
   * accept empty lists should override this method and return {@code true}.
416
   *
417
   * <p>This method should always return a constant value.  It's not specified when this will be
418
   * called.
419
   *
420
   * <p>Note that this method is only called when implementing {@code handleResolvedAddresses()}
421
   * instead of {@code acceptResolvedAddresses()}.
422
   *
423
   * @deprecated Instead of overwriting this and {@code handleResolvedAddresses()}, only
424
   *     overwrite {@code acceptResolvedAddresses()} which indicates if the addresses provided
425
   *     by the name resolver are acceptable with the {@code boolean} return value.
426
   */
427
  @Deprecated
428
  @SuppressWarnings("InlineMeSuggester")
429
  public boolean canHandleEmptyAddressListFromNameResolution() {
430
    return false;
×
431
  }
432

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

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

463
  /**
464
   * Provides arguments for a {@link SubchannelPicker#pickSubchannel(
465
   * LoadBalancer.PickSubchannelArgs)}.
466
   *
467
   * @since 1.2.0
468
   */
469
  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
470
  public abstract static class PickSubchannelArgs {
1 ✔
471

472
    /**
473
     * Call options.
474
     *
475
     * @since 1.2.0
476
     */
477
    public abstract CallOptions getCallOptions();
478

479
    /**
480
     * Headers of the call. {@link SubchannelPicker#pickSubchannel} may mutate it before before
481
     * returning.
482
     *
483
     * @since 1.2.0
484
     */
485
    public abstract Metadata getHeaders();
486

487
    /**
488
     * Call method.
489
     *
490
     * @since 1.2.0
491
     */
492
    public abstract MethodDescriptor<?, ?> getMethodDescriptor();
493

494
    /**
495
     * Gets an object that can be informed about what sort of pick was made.
496
     */
497
    @Internal
498
    public PickDetailsConsumer getPickDetailsConsumer() {
499
      return new PickDetailsConsumer() {};
×
500
    }
501
  }
502

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

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

541
    @Nullable private final Subchannel subchannel;
542
    @Nullable private final ClientStreamTracer.Factory streamTracerFactory;
543
    // An error to be propagated to the application if subchannel == null
544
    // Or OK if there is no error.
545
    // subchannel being null and error being OK means RPC needs to wait
546
    private final Status status;
547
    // True if the result is created by withDrop()
548
    private final boolean drop;
549
    @Nullable private final String authorityOverride;
550
    @Nullable private final String delayType;
551
    @Nullable private final String delayReason;
552

553
    private PickResult(
554
        @Nullable Subchannel subchannel, @Nullable ClientStreamTracer.Factory streamTracerFactory,
555
        Status status, boolean drop) {
556
      this(subchannel, streamTracerFactory, status, drop, null, null, null);
1 ✔
557
    }
1 ✔
558

559
    private PickResult(
560
        @Nullable Subchannel subchannel, @Nullable ClientStreamTracer.Factory streamTracerFactory,
561
        Status status, boolean drop, @Nullable String authorityOverride) {
562
      this(subchannel, streamTracerFactory, status, drop, authorityOverride, null, null);
1 ✔
563
    }
1 ✔
564

565
    private PickResult(
566
        @Nullable Subchannel subchannel, @Nullable ClientStreamTracer.Factory streamTracerFactory,
567
        Status status, boolean drop, @Nullable String authorityOverride,
568
        @Nullable String delayType, @Nullable String delayReason) {
1 ✔
569
      this.subchannel = subchannel;
1 ✔
570
      this.streamTracerFactory = streamTracerFactory;
1 ✔
571
      this.status = checkNotNull(status, "status");
1 ✔
572
      this.drop = drop;
1 ✔
573
      this.authorityOverride = authorityOverride;
1 ✔
574
      this.delayType = delayType;
1 ✔
575
      this.delayReason = delayReason;
1 ✔
576
    }
1 ✔
577

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

657
    /**
658
     * Same as {@code withSubchannel(subchannel, streamTracerFactory)} but with an authority name
659
     * to override in the host header.
660
     */
661
    @ExperimentalApi("https://github.com/grpc/grpc-java/issues/11656")
662
    public static PickResult withSubchannel(
663
        Subchannel subchannel, @Nullable ClientStreamTracer.Factory streamTracerFactory,
664
        @Nullable String authorityOverride) {
665
      return new PickResult(
1 ✔
666
          checkNotNull(subchannel, "subchannel"), streamTracerFactory, Status.OK,
1 ✔
667
          false, authorityOverride);
668
    }
669

670
    /**
671
     * Equivalent to {@code withSubchannel(subchannel, null)}.
672
     *
673
     * @since 1.2.0
674
     */
675
    public static PickResult withSubchannel(Subchannel subchannel) {
676
      return withSubchannel(subchannel, null);
1 ✔
677
    }
678

679
    /**
680
     * Creates a new {@code PickResult} with the given {@code subchannel},
681
     * but retains all other properties from this {@code PickResult}.
682
     *
683
     * @since 1.80.0
684
     */
685
    public PickResult copyWithSubchannel(Subchannel subchannel) {
686
      return new PickResult(checkNotNull(subchannel, "subchannel"), streamTracerFactory,
1 ✔
687
          status, drop, authorityOverride, delayType, delayReason);
688
    }
689

690
    /**
691
     * Creates a new {@code PickResult} with the given {@code streamTracerFactory},
692
     * but retains all other properties from this {@code PickResult}.
693
     *
694
     * @since 1.80.0
695
     */
696
    public PickResult copyWithStreamTracerFactory(
697
        @Nullable ClientStreamTracer.Factory streamTracerFactory) {
698
      return new PickResult(
1 ✔
699
          subchannel, streamTracerFactory, status, drop, authorityOverride, delayType,
700
          delayReason);
701
    }
702

703
    /**
704
     * A decision to report a connectivity error to the RPC.  If the RPC is {@link
705
     * CallOptions#withWaitForReady wait-for-ready}, it will stay buffered.  Otherwise, it will fail
706
     * with the given error.
707
     *
708
     * @param error the error status.  Must not be OK.
709
     * @since 1.2.0
710
     */
711
    public static PickResult withError(Status error) {
712
      Preconditions.checkArgument(!error.isOk(), "error status shouldn't be OK");
1 ✔
713
      return new PickResult(null, null, error, false);
1 ✔
714
    }
715

716
    /**
717
     * A decision to fail an RPC immediately.  This is a final decision and will ignore retry
718
     * policy.
719
     *
720
     * @param status the status with which the RPC will fail.  Must not be OK.
721
     * @since 1.8.0
722
     */
723
    public static PickResult withDrop(Status status) {
724
      Preconditions.checkArgument(!status.isOk(), "drop status shouldn't be OK");
1 ✔
725
      return new PickResult(null, null, status, true);
1 ✔
726
    }
727

728
    /**
729
     * No decision could be made.  The RPC will stay buffered.
730
     *
731
     * @since 1.2.0
732
     */
733
    public static PickResult withNoResult() {
734
      return NO_RESULT;
1 ✔
735
    }
736

737
    /**
738
     * No decision could be made.  The RPC will stay buffered with a specific delay type and reason.
739
     *
740
     * @param delayType low-cardinality root cause label (e.g., "connecting")
741
     * @param delayReason high-cardinality diagnostic string for trace events
742
     * @since 1.86.0
743
     */
744
    public static PickResult withNoResult(String delayType, String delayReason) {
745
      Preconditions.checkNotNull(delayType, "delayType");
1 ✔
746
      Preconditions.checkNotNull(delayReason, "delayReason");
1 ✔
747
      return new PickResult(null, null, Status.OK, false, null, delayType, delayReason);
1 ✔
748
    }
749

750
    /**
751
     * Returns the delay type label if any.
752
     *
753
     * @since 1.86.0
754
     */
755
    @Nullable
756
    public String getDelayType() {
757
      return delayType;
1 ✔
758
    }
759

760
    /**
761
     * Returns the diagnostic delay reason if any.
762
     *
763
     * @since 1.86.0
764
     */
765
    @Nullable
766
    public String getDelayReason() {
767
      return delayReason;
1 ✔
768
    }
769

770
    /** Returns the authority override if any. */
771
    @ExperimentalApi("https://github.com/grpc/grpc-java/issues/11656")
772
    @Nullable
773
    public String getAuthorityOverride() {
774
      return authorityOverride;
1 ✔
775
    }
776

777
    /**
778
     * The Subchannel if this result was created by {@link #withSubchannel withSubchannel()}, or
779
     * null otherwise.
780
     *
781
     * @since 1.2.0
782
     */
783
    @Nullable
784
    public Subchannel getSubchannel() {
785
      return subchannel;
1 ✔
786
    }
787

788
    /**
789
     * The stream tracer factory this result was created with.
790
     *
791
     * @since 1.3.0
792
     */
793
    @Nullable
794
    public ClientStreamTracer.Factory getStreamTracerFactory() {
795
      return streamTracerFactory;
1 ✔
796
    }
797

798
    /**
799
     * The status associated with this result.  Non-{@code OK} if created with {@link #withError
800
     * withError}, or {@code OK} otherwise.
801
     *
802
     * @since 1.2.0
803
     */
804
    public Status getStatus() {
805
      return status;
1 ✔
806
    }
807

808
    /**
809
     * Returns {@code true} if this result was created by {@link #withDrop withDrop()}.
810
     *
811
     * @since 1.8.0
812
     */
813
    public boolean isDrop() {
814
      return drop;
1 ✔
815
    }
816

817
    /**
818
     * Returns {@code true} if the pick was not created with {@link #withNoResult()}.
819
     */
820
    public boolean hasResult() {
821
      return !(subchannel == null && status.isOk());
1 ✔
822
    }
823

824
    @Override
825
    public String toString() {
826
      return MoreObjects.toStringHelper(this)
1 ✔
827
          .add("subchannel", subchannel)
1 ✔
828
          .add("streamTracerFactory", streamTracerFactory)
1 ✔
829
          .add("status", status)
1 ✔
830
          .add("drop", drop)
1 ✔
831
          .add("authority-override", authorityOverride)
1 ✔
832
          .toString();
1 ✔
833
    }
834

835
    @Override
836
    public int hashCode() {
837
      return Objects.hashCode(subchannel, status, streamTracerFactory, drop);
1 ✔
838
    }
839

840
    /**
841
     * Returns true if the {@link Subchannel}, {@link Status}, and
842
     * {@link ClientStreamTracer.Factory} all match.
843
     */
844
    @Override
845
    public boolean equals(Object other) {
846
      if (!(other instanceof PickResult)) {
1 ✔
847
        return false;
×
848
      }
849
      PickResult that = (PickResult) other;
1 ✔
850
      return Objects.equal(subchannel, that.subchannel) && Objects.equal(status, that.status)
1 ✔
851
          && Objects.equal(streamTracerFactory, that.streamTracerFactory)
1 ✔
852
          && drop == that.drop;
853
    }
854
  }
855

856
  /**
857
   * Arguments for creating a {@link Subchannel}.
858
   *
859
   * @since 1.22.0
860
   */
861
  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
862
  public static final class CreateSubchannelArgs {
863
    private final List<EquivalentAddressGroup> addrs;
864
    private final Attributes attrs;
865
    private final Object[][] customOptions;
866

867
    private CreateSubchannelArgs(
868
        List<EquivalentAddressGroup> addrs, Attributes attrs, Object[][] customOptions) {
1 ✔
869
      this.addrs = checkNotNull(addrs, "addresses are not set");
1 ✔
870
      this.attrs = checkNotNull(attrs, "attrs");
1 ✔
871
      this.customOptions = checkNotNull(customOptions, "customOptions");
1 ✔
872
    }
1 ✔
873

874
    /**
875
     * Returns the addresses, which is an unmodifiable list.
876
     */
877
    public List<EquivalentAddressGroup> getAddresses() {
878
      return addrs;
1 ✔
879
    }
880

881
    /**
882
     * Returns the attributes.
883
     */
884
    public Attributes getAttributes() {
885
      return attrs;
1 ✔
886
    }
887

888
    /**
889
     * Get the value for a custom option or its inherent default.
890
     *
891
     * @param key Key identifying option
892
     */
893
    @SuppressWarnings("unchecked")
894
    public <T> T getOption(Key<T> key) {
895
      Preconditions.checkNotNull(key, "key");
1 ✔
896
      for (int i = 0; i < customOptions.length; i++) {
1 ✔
897
        if (key.equals(customOptions[i][0])) {
1 ✔
898
          return (T) customOptions[i][1];
1 ✔
899
        }
900
      }
901
      return key.defaultValue;
1 ✔
902
    }
903

904
    /**
905
     * Returns a builder with the same initial values as this object.
906
     */
907
    public Builder toBuilder() {
908
      return newBuilder().setAddresses(addrs).setAttributes(attrs).copyCustomOptions(customOptions);
1 ✔
909
    }
910

911
    /**
912
     * Creates a new builder.
913
     */
914
    public static Builder newBuilder() {
915
      return new Builder();
1 ✔
916
    }
917

918
    @Override
919
    public String toString() {
920
      return MoreObjects.toStringHelper(this)
1 ✔
921
          .add("addrs", addrs)
1 ✔
922
          .add("attrs", attrs)
1 ✔
923
          .add("customOptions", Arrays.deepToString(customOptions))
1 ✔
924
          .toString();
1 ✔
925
    }
926

927
    @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
928
    public static final class Builder {
929

930
      private static final Object[][] EMPTY_CUSTOM_OPTIONS = new Object[0][2];
1 ✔
931

932
      private List<EquivalentAddressGroup> addrs;
933
      private Attributes attrs = Attributes.EMPTY;
1 ✔
934
      private Object[][] customOptions = EMPTY_CUSTOM_OPTIONS;
1 ✔
935

936
      Builder() {
1 ✔
937
      }
1 ✔
938

939
      private Builder copyCustomOptions(Object[][] options) {
940
        customOptions = new Object[options.length][2];
1 ✔
941
        System.arraycopy(options, 0, customOptions, 0, options.length);
1 ✔
942
        return this;
1 ✔
943
      }
944

945
      /**
946
       * Add a custom option. Any existing value for the key is overwritten.
947
       *
948
       * <p>This is an <strong>optional</strong> property.
949
       *
950
       * @param key the option key
951
       * @param value the option value
952
       */
953
      public <T> Builder addOption(Key<T> key, T value) {
954
        Preconditions.checkNotNull(key, "key");
1 ✔
955
        Preconditions.checkNotNull(value, "value");
1 ✔
956

957
        int existingIdx = -1;
1 ✔
958
        for (int i = 0; i < customOptions.length; i++) {
1 ✔
959
          if (key.equals(customOptions[i][0])) {
1 ✔
960
            existingIdx = i;
1 ✔
961
            break;
1 ✔
962
          }
963
        }
964

965
        if (existingIdx == -1) {
1 ✔
966
          Object[][] newCustomOptions = new Object[customOptions.length + 1][2];
1 ✔
967
          System.arraycopy(customOptions, 0, newCustomOptions, 0, customOptions.length);
1 ✔
968
          customOptions = newCustomOptions;
1 ✔
969
          existingIdx = customOptions.length - 1;
1 ✔
970
        }
971
        customOptions[existingIdx] = new Object[]{key, value};
1 ✔
972
        return this;
1 ✔
973
      }
974

975
      /**
976
       * The addresses to connect to.  All addresses are considered equivalent and will be tried
977
       * in the order they are provided.
978
       */
979
      public Builder setAddresses(EquivalentAddressGroup addrs) {
980
        this.addrs = Collections.singletonList(addrs);
1 ✔
981
        return this;
1 ✔
982
      }
983

984
      /**
985
       * The addresses to connect to.  All addresses are considered equivalent and will
986
       * be tried in the order they are provided.
987
       *
988
       * <p>This is a <strong>required</strong> property.
989
       *
990
       * @throws IllegalArgumentException if {@code addrs} is empty
991
       */
992
      public Builder setAddresses(List<EquivalentAddressGroup> addrs) {
993
        checkArgument(!addrs.isEmpty(), "addrs is empty");
1 ✔
994
        this.addrs = Collections.unmodifiableList(new ArrayList<>(addrs));
1 ✔
995
        return this;
1 ✔
996
      }
997

998
      /**
999
       * Attributes provided here will be included in {@link Subchannel#getAttributes}.
1000
       *
1001
       * <p>This is an <strong>optional</strong> property.  Default is empty if not set.
1002
       */
1003
      public Builder setAttributes(Attributes attrs) {
1004
        this.attrs = checkNotNull(attrs, "attrs");
1 ✔
1005
        return this;
1 ✔
1006
      }
1007

1008
      /**
1009
       * Creates a new args object.
1010
       */
1011
      public CreateSubchannelArgs build() {
1012
        return new CreateSubchannelArgs(addrs, attrs, customOptions);
1 ✔
1013
      }
1014
    }
1015

1016
    /**
1017
     * Key for a key-value pair. Uses reference equality.
1018
     */
1019
    @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
1020
    public static final class Key<T> {
1021

1022
      private final String debugString;
1023
      private final T defaultValue;
1024

1025
      private Key(String debugString, T defaultValue) {
1 ✔
1026
        this.debugString = debugString;
1 ✔
1027
        this.defaultValue = defaultValue;
1 ✔
1028
      }
1 ✔
1029

1030
      /**
1031
       * Factory method for creating instances of {@link Key}. The default value of the key is
1032
       * {@code null}.
1033
       *
1034
       * @param debugString a debug string that describes this key.
1035
       * @param <T> Key type
1036
       * @return Key object
1037
       */
1038
      public static <T> Key<T> create(String debugString) {
1039
        Preconditions.checkNotNull(debugString, "debugString");
1 ✔
1040
        return new Key<>(debugString, /*defaultValue=*/ null);
1 ✔
1041
      }
1042

1043
      /**
1044
       * Factory method for creating instances of {@link Key}.
1045
       *
1046
       * @param debugString a debug string that describes this key.
1047
       * @param defaultValue default value to return when value for key not set
1048
       * @param <T> Key type
1049
       * @return Key object
1050
       */
1051
      public static <T> Key<T> createWithDefault(String debugString, T defaultValue) {
1052
        Preconditions.checkNotNull(debugString, "debugString");
1 ✔
1053
        return new Key<>(debugString, defaultValue);
1 ✔
1054
      }
1055

1056
      /**
1057
       * Returns the user supplied default value for this key.
1058
       */
1059
      public T getDefault() {
1060
        return defaultValue;
×
1061
      }
1062

1063
      @Override
1064
      public String toString() {
1065
        return debugString;
1 ✔
1066
      }
1067
    }
1068
  }
1069

1070
  /**
1071
   * Provides essentials for LoadBalancer implementations.
1072
   *
1073
   * <p>This class is thread-safe.
1074
   *
1075
   * @since 1.2.0
1076
   */
1077
  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
1078
  public abstract static class Helper {
1 ✔
1079
    /**
1080
     * Creates a Subchannel, which is a logical connection to the given group of addresses which are
1081
     * considered equivalent.  The {@code attrs} are custom attributes associated with this
1082
     * Subchannel, and can be accessed later through {@link Subchannel#getAttributes
1083
     * Subchannel.getAttributes()}.
1084
     *
1085
     * <p>The LoadBalancer is responsible for closing unused Subchannels, and closing all
1086
     * Subchannels within {@link #shutdown}.
1087
     *
1088
     * <p>It must be called from {@link #getSynchronizationContext the Synchronization Context}
1089
     *
1090
     * @return Must return a valid Subchannel object, may not return null.
1091
     *
1092
     * @since 1.22.0
1093
     */
1094
    public Subchannel createSubchannel(CreateSubchannelArgs args) {
1095
      throw new UnsupportedOperationException();
1 ✔
1096
    }
1097

1098
    /**
1099
     * Create an out-of-band channel for the LoadBalancer’s own RPC needs, e.g., talking to an
1100
     * external load-balancer service.
1101
     *
1102
     * <p>The LoadBalancer is responsible for closing unused OOB channels, and closing all OOB
1103
     * channels within {@link #shutdown}.
1104
     *
1105
     * @since 1.4.0
1106
     */
1107
    public abstract ManagedChannel createOobChannel(EquivalentAddressGroup eag, String authority);
1108

1109
    /**
1110
     * Create an out-of-band channel for the LoadBalancer's own RPC needs, e.g., talking to an
1111
     * external load-balancer service. This version of the method allows multiple EAGs, so different
1112
     * addresses can have different authorities.
1113
     *
1114
     * <p>The LoadBalancer is responsible for closing unused OOB channels, and closing all OOB
1115
     * channels within {@link #shutdown}.
1116
     * */
1117
    public ManagedChannel createOobChannel(List<EquivalentAddressGroup> eag,
1118
        String authority) {
1119
      throw new UnsupportedOperationException();
×
1120
    }
1121

1122
    /**
1123
     * Updates the addresses used for connections in the {@code Channel} that was created by {@link
1124
     * #createOobChannel(EquivalentAddressGroup, String)}. This is superior to {@link
1125
     * #createOobChannel(EquivalentAddressGroup, String)} when the old and new addresses overlap,
1126
     * since the channel can continue using an existing connection.
1127
     *
1128
     * @throws IllegalArgumentException if {@code channel} was not returned from {@link
1129
     *     #createOobChannel}
1130
     * @since 1.4.0
1131
     */
1132
    public void updateOobChannelAddresses(ManagedChannel channel, EquivalentAddressGroup eag) {
1133
      throw new UnsupportedOperationException();
×
1134
    }
1135

1136
    /**
1137
     * Updates the addresses with a new EAG list. Connection is continued when old and new addresses
1138
     * overlap.
1139
     * */
1140
    public void updateOobChannelAddresses(ManagedChannel channel,
1141
        List<EquivalentAddressGroup> eag) {
1142
      throw new UnsupportedOperationException();
×
1143
    }
1144

1145
    /**
1146
     * Creates an out-of-band channel for LoadBalancer's own RPC needs, e.g., talking to an external
1147
     * load-balancer service, that is specified by a target string.  See the documentation on
1148
     * {@link ManagedChannelBuilder#forTarget} for the format of a target string.
1149
     *
1150
     * <p>The target string will be resolved by a {@link NameResolver} created according to the
1151
     * target string.
1152
     *
1153
     * <p>The LoadBalancer is responsible for closing unused OOB channels, and closing all OOB
1154
     * channels within {@link #shutdown}.
1155
     *
1156
     * @since 1.20.0
1157
     */
1158
    public ManagedChannel createResolvingOobChannel(String target) {
1159
      return createResolvingOobChannelBuilder(target).build();
1 ✔
1160
    }
1161

1162
    /**
1163
     * Creates an out-of-band channel builder for LoadBalancer's own RPC needs, e.g., talking to an
1164
     * external load-balancer service, that is specified by a target string.  See the documentation
1165
     * on {@link ManagedChannelBuilder#forTarget} for the format of a target string.
1166
     *
1167
     * <p>The target string will be resolved by a {@link NameResolver} created according to the
1168
     * target string.
1169
     *
1170
     * <p>The returned oob-channel builder defaults to use the same authority and ChannelCredentials
1171
     * (without bearer tokens) as the parent channel's for authentication. This is different from
1172
     * {@link #createResolvingOobChannelBuilder(String, ChannelCredentials)}.
1173
     *
1174
     * <p>The LoadBalancer is responsible for closing unused OOB channels, and closing all OOB
1175
     * channels within {@link #shutdown}.
1176
     *
1177
     * @deprecated Use {@link #createResolvingOobChannelBuilder(String, ChannelCredentials)}
1178
     *     instead.
1179
     * @since 1.31.0
1180
     */
1181
    @Deprecated
1182
    public ManagedChannelBuilder<?> createResolvingOobChannelBuilder(String target) {
1183
      throw new UnsupportedOperationException("Not implemented");
×
1184
    }
1185

1186
    /**
1187
     * Creates an out-of-band channel builder for LoadBalancer's own RPC needs, e.g., talking to an
1188
     * external load-balancer service, that is specified by a target string and credentials.  See
1189
     * the documentation on {@link Grpc#newChannelBuilder} for the format of a target string.
1190
     *
1191
     * <p>The target string will be resolved by a {@link NameResolver} created according to the
1192
     * target string.
1193
     *
1194
     * <p>The LoadBalancer is responsible for closing unused OOB channels, and closing all OOB
1195
     * channels within {@link #shutdown}.
1196
     *
1197
     * @since 1.35.0
1198
     */
1199
    public ManagedChannelBuilder<?> createResolvingOobChannelBuilder(
1200
        String target, ChannelCredentials creds) {
1201
      throw new UnsupportedOperationException();
×
1202
    }
1203

1204
    /**
1205
     * Set a new state with a new picker to the channel.
1206
     *
1207
     * <p>When a new picker is provided via {@code updateBalancingState()}, the channel will apply
1208
     * the picker on all buffered RPCs, by calling {@link SubchannelPicker#pickSubchannel(
1209
     * LoadBalancer.PickSubchannelArgs)}.
1210
     *
1211
     * <p>The channel will hold the picker and use it for all RPCs, until {@code
1212
     * updateBalancingState()} is called again and a new picker replaces the old one.  If {@code
1213
     * updateBalancingState()} has never been called, the channel will buffer all RPCs until a
1214
     * picker is provided.
1215
     *
1216
     * <p>It should be called from the Synchronization Context.  Currently will log a warning if
1217
     * violated.  It will become an exception eventually.  See <a
1218
     * href="https://github.com/grpc/grpc-java/issues/5015">#5015</a> for the background.
1219
     *
1220
     * <p>The passed state will be the channel's new state. The SHUTDOWN state should not be passed
1221
     * and its behavior is undefined.
1222
     *
1223
     * @since 1.6.0
1224
     */
1225
    public abstract void updateBalancingState(
1226
        @Nonnull ConnectivityState newState, @Nonnull SubchannelPicker newPicker);
1227

1228
    /**
1229
     * Call {@link NameResolver#refresh} on the channel's resolver.
1230
     *
1231
     * <p>It should be called from the Synchronization Context.  Currently will log a warning if
1232
     * violated.  It will become an exception eventually.  See <a
1233
     * href="https://github.com/grpc/grpc-java/issues/5015">#5015</a> for the background.
1234
     *
1235
     * @since 1.18.0
1236
     */
1237
    public void refreshNameResolution() {
1238
      throw new UnsupportedOperationException();
×
1239
    }
1240

1241
    /**
1242
     * Historically the channel automatically refreshes name resolution if any subchannel
1243
     * connection is broken. It's transitioning to let load balancers make the decision. To
1244
     * avoid silent breakages, the channel checks if {@link #refreshNameResolution} is called
1245
     * by the load balancer. If not, it will do it and log a warning. This will be removed in
1246
     * the future and load balancers are completely responsible for triggering the refresh.
1247
     * See <a href="https://github.com/grpc/grpc-java/issues/8088">#8088</a> for the background.
1248
     *
1249
     * <p>This should rarely be used, but sometimes the address for the subchannel wasn't
1250
     * provided by the name resolver and a refresh needs to be directed somewhere else instead.
1251
     * Then you can call this method to disable the short-tem check for detecting LoadBalancers
1252
     * that need to be updated for the new expected behavior.
1253
     *
1254
     * @since 1.38.0
1255
     * @deprecated Warning has been removed
1256
     */
1257
    @ExperimentalApi("https://github.com/grpc/grpc-java/issues/8088")
1258
    @Deprecated
1259
    public void ignoreRefreshNameResolutionCheck() {
1260
      // no-op
1261
    }
×
1262

1263
    /**
1264
     * Returns a {@link SynchronizationContext} that runs tasks in the same Synchronization Context
1265
     * as that the callback methods on the {@link LoadBalancer} interface are run in.
1266
     *
1267
     * <p>Work added to the synchronization context might not run immediately, so LB implementations
1268
     * must be careful to ensure that any assumptions still hold when it is executed. In particular,
1269
     * the LB might have been shut down or subchannels might have changed state.
1270
     *
1271
     * <p>Pro-tip: in order to call {@link SynchronizationContext#schedule}, you need to provide a
1272
     * {@link ScheduledExecutorService}.  {@link #getScheduledExecutorService} is provided for your
1273
     * convenience.
1274
     *
1275
     * @since 1.17.0
1276
     */
1277
    public SynchronizationContext getSynchronizationContext() {
1278
      // TODO(zhangkun): make getSynchronizationContext() abstract after runSerialized() is deleted
1279
      throw new UnsupportedOperationException();
×
1280
    }
1281

1282
    /**
1283
     * Returns a {@link ScheduledExecutorService} for scheduling delayed tasks.
1284
     *
1285
     * <p>This service is a shared resource and is only meant for quick tasks.  DO NOT block or run
1286
     * time-consuming tasks.
1287
     *
1288
     * <p>The returned service doesn't support {@link ScheduledExecutorService#shutdown shutdown()}
1289
     * and {@link ScheduledExecutorService#shutdownNow shutdownNow()}.  They will throw if called.
1290
     *
1291
     * @since 1.17.0
1292
     */
1293
    public ScheduledExecutorService getScheduledExecutorService() {
1294
      throw new UnsupportedOperationException();
×
1295
    }
1296

1297
    /**
1298
     * Returns the authority string of the channel, which is derived from the DNS-style target name.
1299
     * If overridden by a load balancer, {@link #getUnsafeChannelCredentials} must also be
1300
     * overridden to call {@link #getChannelCredentials} or provide appropriate credentials.
1301
     *
1302
     * @since 1.2.0
1303
     */
1304
    public abstract String getAuthority();
1305

1306
    /**
1307
     * Returns the target string of the channel, guaranteed to include its scheme.
1308
     */
1309
    public String getChannelTarget() {
1310
      throw new UnsupportedOperationException();
×
1311
    }
1312

1313
    /**
1314
     * Returns the ChannelCredentials used to construct the channel, without bearer tokens.
1315
     *
1316
     * @since 1.35.0
1317
     */
1318
    public ChannelCredentials getChannelCredentials() {
1319
      return getUnsafeChannelCredentials().withoutBearerTokens();
×
1320
    }
1321

1322
    /**
1323
     * Returns the UNSAFE ChannelCredentials used to construct the channel,
1324
     * including bearer tokens. Load balancers should generally have no use for
1325
     * these credentials and use of them is heavily discouraged. These must be used
1326
     * <em>very</em> carefully to avoid sending bearer tokens to untrusted servers
1327
     * as the server could then impersonate the client. Generally it is only safe
1328
     * to use these credentials when communicating with the backend.
1329
     *
1330
     * @since 1.35.0
1331
     */
1332
    public ChannelCredentials getUnsafeChannelCredentials() {
1333
      throw new UnsupportedOperationException();
×
1334
    }
1335

1336
    /**
1337
     * Returns the {@link ChannelLogger} for the Channel served by this LoadBalancer.
1338
     *
1339
     * @since 1.17.0
1340
     */
1341
    public ChannelLogger getChannelLogger() {
1342
      throw new UnsupportedOperationException();
×
1343
    }
1344

1345
    /**
1346
     * Returns the {@link NameResolver.Args} that the Channel uses to create {@link NameResolver}s.
1347
     *
1348
     * @since 1.22.0
1349
     */
1350
    public NameResolver.Args getNameResolverArgs() {
1351
      throw new UnsupportedOperationException();
×
1352
    }
1353

1354
    /**
1355
     * Returns the {@link NameResolverRegistry} that the Channel uses to look for {@link
1356
     * NameResolver}s.
1357
     *
1358
     * @since 1.22.0
1359
     */
1360
    public NameResolverRegistry getNameResolverRegistry() {
1361
      throw new UnsupportedOperationException();
×
1362
    }
1363

1364
    /**
1365
     * Returns the {@link MetricRecorder} that the channel uses to record metrics.
1366
     *
1367
     * @since 1.64.0
1368
     */
1369
    @Internal
1370
    public MetricRecorder getMetricRecorder() {
1371
      return new MetricRecorder() {};
×
1372
    }
1373
  }
1374

1375
  /**
1376
   * A logical connection to a server, or a group of equivalent servers represented by an {@link
1377
   * EquivalentAddressGroup}.
1378
   *
1379
   * <p>It maintains at most one physical connection (aka transport) for sending new RPCs, while
1380
   * also keeps track of previous transports that has been shut down but not terminated yet.
1381
   *
1382
   * <p>If there isn't an active transport yet, and an RPC is assigned to the Subchannel, it will
1383
   * create a new transport.  It won't actively create transports otherwise.  {@link
1384
   * #requestConnection requestConnection()} can be used to ask Subchannel to create a transport if
1385
   * there isn't any.
1386
   *
1387
   * <p>{@link #start} must be called prior to calling any other methods, with the exception of
1388
   * {@link #shutdown}, which can be called at any time.
1389
   *
1390
   * @since 1.2.0
1391
   */
1392
  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
1393
  public abstract static class Subchannel {
1 ✔
1394
    /**
1395
     * Starts the Subchannel.  Can only be called once.
1396
     *
1397
     * <p>Must be called prior to any other method on this class, except for {@link #shutdown} which
1398
     * may be called at any time.
1399
     *
1400
     * <p>Must be called from the {@link Helper#getSynchronizationContext Synchronization Context},
1401
     * otherwise it may throw.  See <a href="https://github.com/grpc/grpc-java/issues/5015">
1402
     * #5015</a> for more discussions.
1403
     *
1404
     * @param listener receives state updates for this Subchannel.
1405
     */
1406
    public void start(SubchannelStateListener listener) {
1407
      throw new UnsupportedOperationException("Not implemented");
×
1408
    }
1409

1410
    /**
1411
     * Shuts down the Subchannel.  After this method is called, this Subchannel should no longer
1412
     * be returned by the latest {@link SubchannelPicker picker}, and can be safely discarded.
1413
     *
1414
     * <p>Calling it on an already shut-down Subchannel has no effect.
1415
     *
1416
     * <p>It should be called from the Synchronization Context.  Currently will log a warning if
1417
     * violated.  It will become an exception eventually.  See <a
1418
     * href="https://github.com/grpc/grpc-java/issues/5015">#5015</a> for the background.
1419
     *
1420
     * @since 1.2.0
1421
     */
1422
    public abstract void shutdown();
1423

1424
    /**
1425
     * Asks the Subchannel to create a connection (aka transport), if there isn't an active one.
1426
     *
1427
     * <p>It should be called from the Synchronization Context.  Currently will log a warning if
1428
     * violated.  It will become an exception eventually.  See <a
1429
     * href="https://github.com/grpc/grpc-java/issues/5015">#5015</a> for the background.
1430
     *
1431
     * @since 1.2.0
1432
     */
1433
    public abstract void requestConnection();
1434

1435
    /**
1436
     * Returns the addresses that this Subchannel is bound to.  This can be called only if
1437
     * the Subchannel has only one {@link EquivalentAddressGroup}.  Under the hood it calls
1438
     * {@link #getAllAddresses}.
1439
     *
1440
     * <p>It should be called from the Synchronization Context.  Currently will log a warning if
1441
     * violated.  It will become an exception eventually.  See <a
1442
     * href="https://github.com/grpc/grpc-java/issues/5015">#5015</a> for the background.
1443
     *
1444
     * @throws IllegalStateException if this subchannel has more than one EquivalentAddressGroup.
1445
     *         Use {@link #getAllAddresses} instead
1446
     * @since 1.2.0
1447
     */
1448
    public final EquivalentAddressGroup getAddresses() {
1449
      List<EquivalentAddressGroup> groups = getAllAddresses();
1 ✔
1450
      Preconditions.checkState(groups != null && groups.size() == 1,
1 ✔
1451
          "%s does not have exactly one group", groups);
1452
      return groups.get(0);
1 ✔
1453
    }
1454

1455
    /**
1456
     * Returns the addresses that this Subchannel is bound to. The returned list will not be empty.
1457
     *
1458
     * <p>It should be called from the Synchronization Context.  Currently will log a warning if
1459
     * violated.  It will become an exception eventually.  See <a
1460
     * href="https://github.com/grpc/grpc-java/issues/5015">#5015</a> for the background.
1461
     *
1462
     * @since 1.14.0
1463
     */
1464
    public List<EquivalentAddressGroup> getAllAddresses() {
1465
      throw new UnsupportedOperationException();
×
1466
    }
1467

1468
    /**
1469
     * The same attributes passed to {@link Helper#createSubchannel Helper.createSubchannel()}.
1470
     * LoadBalancer can use it to attach additional information here, e.g., the shard this
1471
     * Subchannel belongs to.
1472
     *
1473
     * @since 1.2.0
1474
     */
1475
    public abstract Attributes getAttributes();
1476

1477
    /**
1478
     * (Internal use only) returns a {@link Channel} that is backed by this Subchannel.  This allows
1479
     * a LoadBalancer to issue its own RPCs for auxiliary purposes, such as health-checking, on
1480
     * already-established connections.  This channel has certain restrictions:
1481
     * <ol>
1482
     *   <li>It can issue RPCs only if the Subchannel is {@code READY}. If {@link
1483
     *   Channel#newCall} is called when the Subchannel is not {@code READY}, the RPC will fail
1484
     *   immediately.</li>
1485
     *   <li>It doesn't support {@link CallOptions#withWaitForReady wait-for-ready} RPCs. Such RPCs
1486
     *   will fail immediately.</li>
1487
     * </ol>
1488
     *
1489
     * <p>RPCs made on this Channel is not counted when determining ManagedChannel's {@link
1490
     * ManagedChannelBuilder#idleTimeout idle mode}.  In other words, they won't prevent
1491
     * ManagedChannel from entering idle mode.
1492
     *
1493
     * <p>Warning: RPCs made on this channel will prevent a shut-down transport from terminating. If
1494
     * you make long-running RPCs, you need to make sure they will finish in time after the
1495
     * Subchannel has transitioned away from {@code READY} state
1496
     * (notified through {@link #handleSubchannelState}).
1497
     *
1498
     * <p>Warning: this is INTERNAL API, is not supposed to be used by external users, and may
1499
     * change without notice. If you think you must use it, please file an issue.
1500
     */
1501
    @Internal
1502
    public Channel asChannel() {
1503
      throw new UnsupportedOperationException();
×
1504
    }
1505

1506
    /**
1507
     * Returns a {@link ChannelLogger} for this Subchannel.
1508
     *
1509
     * @since 1.17.0
1510
     */
1511
    public ChannelLogger getChannelLogger() {
1512
      throw new UnsupportedOperationException();
×
1513
    }
1514

1515
    /**
1516
     * Replaces the existing addresses used with this {@code Subchannel}. If the new and old
1517
     * addresses overlap, the Subchannel can continue using an existing connection.
1518
     *
1519
     * <p>It must be called from the Synchronization Context or will throw.
1520
     *
1521
     * @throws IllegalArgumentException if {@code addrs} is empty
1522
     * @since 1.22.0
1523
     */
1524
    public void updateAddresses(List<EquivalentAddressGroup> addrs) {
1525
      throw new UnsupportedOperationException();
×
1526
    }
1527

1528
    /**
1529
     * (Internal use only) returns an object that represents the underlying subchannel that is used
1530
     * by the Channel for sending RPCs when this {@link Subchannel} is picked.  This is an opaque
1531
     * object that is both provided and consumed by the Channel.  Its type <strong>is not</strong>
1532
     * {@code Subchannel}.
1533
     *
1534
     * <p>Warning: this is INTERNAL API, is not supposed to be used by external users, and may
1535
     * change without notice. If you think you must use it, please file an issue and we can consider
1536
     * removing its "internal" status.
1537
     */
1538
    @Internal
1539
    public Object getInternalSubchannel() {
1540
      throw new UnsupportedOperationException();
×
1541
    }
1542

1543
    /**
1544
     * (Internal use only) returns attributes of the address subchannel is connected to.
1545
     *
1546
     * <p>Warning: this is INTERNAL API, is not supposed to be used by external users, and may
1547
     * change without notice. If you think you must use it, please file an issue and we can consider
1548
     * removing its "internal" status.
1549
     */
1550
    @Internal
1551
    public Attributes getConnectedAddressAttributes() {
1552
      throw new UnsupportedOperationException();
×
1553
    }
1554
  }
1555

1556
  /**
1557
   * Receives state changes for one {@link Subchannel}. All methods are run under {@link
1558
   * Helper#getSynchronizationContext}.
1559
   *
1560
   * @since 1.22.0
1561
   */
1562
  public interface SubchannelStateListener {
1563
    /**
1564
     * Handles a state change on a Subchannel.
1565
     *
1566
     * <p>The initial state of a Subchannel is IDLE. You won't get a notification for the initial
1567
     * IDLE state.
1568
     *
1569
     * <p>If the new state is not SHUTDOWN, this method should create a new picker and call {@link
1570
     * Helper#updateBalancingState Helper.updateBalancingState()}.  Failing to do so may result in
1571
     * unnecessary delays of RPCs. Please refer to {@link PickResult#withSubchannel
1572
     * PickResult.withSubchannel()}'s javadoc for more information.
1573
     *
1574
     * <p>When a subchannel's state is IDLE or TRANSIENT_FAILURE and the address for the subchannel
1575
     * was received in {@link LoadBalancer#handleResolvedAddresses}, load balancers should call
1576
     * {@link Helper#refreshNameResolution} to inform polling name resolvers that it is an
1577
     * appropriate time to refresh the addresses. Without the refresh, changes to the addresses may
1578
     * never be detected.
1579
     *
1580
     * <p>SHUTDOWN can only happen in two cases.  One is that LoadBalancer called {@link
1581
     * Subchannel#shutdown} earlier, thus it should have already discarded this Subchannel.  The
1582
     * other is that Channel is doing a {@link ManagedChannel#shutdownNow forced shutdown} or has
1583
     * already terminated, thus there won't be further requests to LoadBalancer.  Therefore, the
1584
     * LoadBalancer usually don't need to react to a SHUTDOWN state.
1585
     *
1586
     * @param newState the new state
1587
     * @since 1.22.0
1588
     */
1589
    void onSubchannelState(ConnectivityStateInfo newState);
1590
  }
1591

1592
  /**
1593
   * Factory to create {@link LoadBalancer} instance.
1594
   *
1595
   * <p>This class is thread-safe.
1596
   *
1597
   * @since 1.2.0
1598
   */
1599
  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
1600
  public abstract static class Factory {
1 ✔
1601
    /**
1602
     * Creates a {@link LoadBalancer} that will be used inside a channel.
1603
     *
1604
     * @since 1.2.0
1605
     */
1606
    public abstract LoadBalancer newLoadBalancer(Helper helper);
1607
  }
1608

1609
  /**
1610
   * A picker that always returns an erring pick.
1611
   *
1612
   * @deprecated Use {@code new FixedResultPicker(PickResult.withError(error))} instead.
1613
   */
1614
  @Deprecated
1615
  public static final class ErrorPicker extends SubchannelPicker {
1616

1617
    private final Status error;
1618

1619
    public ErrorPicker(Status error) {
×
1620
      this.error = checkNotNull(error, "error");
×
1621
    }
×
1622

1623
    @Override
1624
    public PickResult pickSubchannel(PickSubchannelArgs args) {
1625
      return PickResult.withError(error);
×
1626
    }
1627

1628
    @Override
1629
    public String toString() {
1630
      return MoreObjects.toStringHelper(this)
×
1631
          .add("error", error)
×
1632
          .toString();
×
1633
    }
1634
  }
1635

1636
  /** A picker that always returns the same result. */
1637
  public static final class FixedResultPicker extends SubchannelPicker {
1638
    private final PickResult result;
1639

1640
    public FixedResultPicker(PickResult result) {
1 ✔
1641
      this.result = Preconditions.checkNotNull(result, "result");
1 ✔
1642
    }
1 ✔
1643

1644
    @Override
1645
    public PickResult pickSubchannel(PickSubchannelArgs args) {
1646
      return result;
1 ✔
1647
    }
1648

1649
    @Override
1650
    public String toString() {
1651
      return "FixedResultPicker(" + result + ")";
1 ✔
1652
    }
1653

1654
    @Override
1655
    public int hashCode() {
1656
      return result.hashCode();
1 ✔
1657
    }
1658

1659
    @Override
1660
    public boolean equals(Object o) {
1661
      if (!(o instanceof FixedResultPicker)) {
1 ✔
1662
        return false;
1 ✔
1663
      }
1664
      FixedResultPicker that = (FixedResultPicker) o;
1 ✔
1665
      return this.result.equals(that.result);
1 ✔
1666
    }
1667
  }
1668
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc