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

grpc / grpc-java / #19447

31 Aug 2024 11:07PM CUT coverage: 84.561% (+0.04%) from 84.523%
#19447

push

github

web-flow
xds: Fix load reporting when pick first is used for locality-routing. (#11495)

* Determine subchannel's network locality from connected address, instead of assuming that all addresses for a subchannel are in the same locality.

33554 of 39680 relevant lines covered (84.56%)

0.85 hits per line

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

76.67
/../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 Attributes.Key<Boolean>
126
      HAS_HEALTH_PRODUCER_LISTENER_KEY =
1✔
127
      Attributes.Key.create("internal:has-health-check-producer-listener");
1✔
128

129
  public static final Attributes.Key<Boolean> IS_PETIOLE_POLICY =
1✔
130
      Attributes.Key.create("io.grpc.IS_PETIOLE_POLICY");
1✔
131

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

144
    @Override
145
    public String toString() {
146
      return "EMPTY_PICKER";
×
147
    }
148
  };
149

150
  private int recursionCount;
151

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

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

198
      return Status.OK;
1✔
199
    }
200
  }
201

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

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

228
    /**
229
     * Factory for constructing a new Builder.
230
     *
231
     * @since 1.21.0
232
     */
233
    public static Builder newBuilder() {
234
      return new Builder();
1✔
235
    }
236

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

249
    /**
250
     * Gets the server addresses.
251
     *
252
     * @since 1.21.0
253
     */
254
    public List<EquivalentAddressGroup> getAddresses() {
255
      return addresses;
1✔
256
    }
257

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

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

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

291
      Builder() {}
1✔
292

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

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

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

324
      /**
325
       * Constructs the {@link ResolvedAddresses}.
326
       */
327
      public ResolvedAddresses build() {
328
        return new ResolvedAddresses(addresses, attributes, loadBalancingPolicyConfig);
1✔
329
      }
330
    }
331

332
    @Override
333
    public String toString() {
334
      return MoreObjects.toStringHelper(this)
1✔
335
          .add("addresses", addresses)
1✔
336
          .add("attributes", attributes)
1✔
337
          .add("loadBalancingPolicyConfig", loadBalancingPolicyConfig)
1✔
338
          .toString();
1✔
339
    }
340

341
    @Override
342
    public int hashCode() {
343
      return Objects.hashCode(addresses, attributes, loadBalancingPolicyConfig);
×
344
    }
345

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

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

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

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

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

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

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

450
    /**
451
     * Tries to establish connections now so that the upcoming RPC may then just pick a ready
452
     * connection without having to connect first.
453
     *
454
     * <p>No-op if unsupported.
455
     *
456
     * @deprecated override {@link LoadBalancer#requestConnection} instead.
457
     * @since 1.11.0
458
     */
459
    @Deprecated
460
    public void requestConnection() {}
×
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

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

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

636
    /**
637
     * Equivalent to {@code withSubchannel(subchannel, null)}.
638
     *
639
     * @since 1.2.0
640
     */
641
    public static PickResult withSubchannel(Subchannel subchannel) {
642
      return withSubchannel(subchannel, null);
1✔
643
    }
644

645
    /**
646
     * A decision to report a connectivity error to the RPC.  If the RPC is {@link
647
     * CallOptions#withWaitForReady wait-for-ready}, it will stay buffered.  Otherwise, it will fail
648
     * with the given error.
649
     *
650
     * @param error the error status.  Must not be OK.
651
     * @since 1.2.0
652
     */
653
    public static PickResult withError(Status error) {
654
      Preconditions.checkArgument(!error.isOk(), "error status shouldn't be OK");
1✔
655
      return new PickResult(null, null, error, false);
1✔
656
    }
657

658
    /**
659
     * A decision to fail an RPC immediately.  This is a final decision and will ignore retry
660
     * policy.
661
     *
662
     * @param status the status with which the RPC will fail.  Must not be OK.
663
     * @since 1.8.0
664
     */
665
    public static PickResult withDrop(Status status) {
666
      Preconditions.checkArgument(!status.isOk(), "drop status shouldn't be OK");
1✔
667
      return new PickResult(null, null, status, true);
1✔
668
    }
669

670
    /**
671
     * No decision could be made.  The RPC will stay buffered.
672
     *
673
     * @since 1.2.0
674
     */
675
    public static PickResult withNoResult() {
676
      return NO_RESULT;
1✔
677
    }
678

679
    /**
680
     * The Subchannel if this result was created by {@link #withSubchannel withSubchannel()}, or
681
     * null otherwise.
682
     *
683
     * @since 1.2.0
684
     */
685
    @Nullable
686
    public Subchannel getSubchannel() {
687
      return subchannel;
1✔
688
    }
689

690
    /**
691
     * The stream tracer factory this result was created with.
692
     *
693
     * @since 1.3.0
694
     */
695
    @Nullable
696
    public ClientStreamTracer.Factory getStreamTracerFactory() {
697
      return streamTracerFactory;
1✔
698
    }
699

700
    /**
701
     * The status associated with this result.  Non-{@code OK} if created with {@link #withError
702
     * withError}, or {@code OK} otherwise.
703
     *
704
     * @since 1.2.0
705
     */
706
    public Status getStatus() {
707
      return status;
1✔
708
    }
709

710
    /**
711
     * Returns {@code true} if this result was created by {@link #withDrop withDrop()}.
712
     *
713
     * @since 1.8.0
714
     */
715
    public boolean isDrop() {
716
      return drop;
1✔
717
    }
718

719
    /**
720
     * Returns {@code true} if the pick was not created with {@link #withNoResult()}.
721
     */
722
    public boolean hasResult() {
723
      return !(subchannel == null && status.isOk());
1✔
724
    }
725

726
    @Override
727
    public String toString() {
728
      return MoreObjects.toStringHelper(this)
1✔
729
          .add("subchannel", subchannel)
1✔
730
          .add("streamTracerFactory", streamTracerFactory)
1✔
731
          .add("status", status)
1✔
732
          .add("drop", drop)
1✔
733
          .toString();
1✔
734
    }
735

736
    @Override
737
    public int hashCode() {
738
      return Objects.hashCode(subchannel, status, streamTracerFactory, drop);
×
739
    }
740

741
    /**
742
     * Returns true if the {@link Subchannel}, {@link Status}, and
743
     * {@link ClientStreamTracer.Factory} all match.
744
     */
745
    @Override
746
    public boolean equals(Object other) {
747
      if (!(other instanceof PickResult)) {
1✔
748
        return false;
×
749
      }
750
      PickResult that = (PickResult) other;
1✔
751
      return Objects.equal(subchannel, that.subchannel) && Objects.equal(status, that.status)
1✔
752
          && Objects.equal(streamTracerFactory, that.streamTracerFactory)
1✔
753
          && drop == that.drop;
754
    }
755
  }
756

757
  /**
758
   * Arguments for creating a {@link Subchannel}.
759
   *
760
   * @since 1.22.0
761
   */
762
  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
763
  public static final class CreateSubchannelArgs {
764
    private final List<EquivalentAddressGroup> addrs;
765
    private final Attributes attrs;
766
    private final Object[][] customOptions;
767

768
    private CreateSubchannelArgs(
769
        List<EquivalentAddressGroup> addrs, Attributes attrs, Object[][] customOptions) {
1✔
770
      this.addrs = checkNotNull(addrs, "addresses are not set");
1✔
771
      this.attrs = checkNotNull(attrs, "attrs");
1✔
772
      this.customOptions = checkNotNull(customOptions, "customOptions");
1✔
773
    }
1✔
774

775
    /**
776
     * Returns the addresses, which is an unmodifiable list.
777
     */
778
    public List<EquivalentAddressGroup> getAddresses() {
779
      return addrs;
1✔
780
    }
781

782
    /**
783
     * Returns the attributes.
784
     */
785
    public Attributes getAttributes() {
786
      return attrs;
1✔
787
    }
788

789
    /**
790
     * Get the value for a custom option or its inherent default.
791
     *
792
     * @param key Key identifying option
793
     */
794
    @SuppressWarnings("unchecked")
795
    public <T> T getOption(Key<T> key) {
796
      Preconditions.checkNotNull(key, "key");
1✔
797
      for (int i = 0; i < customOptions.length; i++) {
1✔
798
        if (key.equals(customOptions[i][0])) {
1✔
799
          return (T) customOptions[i][1];
1✔
800
        }
801
      }
802
      return key.defaultValue;
1✔
803
    }
804

805
    /**
806
     * Returns a builder with the same initial values as this object.
807
     */
808
    public Builder toBuilder() {
809
      return newBuilder().setAddresses(addrs).setAttributes(attrs).copyCustomOptions(customOptions);
1✔
810
    }
811

812
    /**
813
     * Creates a new builder.
814
     */
815
    public static Builder newBuilder() {
816
      return new Builder();
1✔
817
    }
818

819
    @Override
820
    public String toString() {
821
      return MoreObjects.toStringHelper(this)
1✔
822
          .add("addrs", addrs)
1✔
823
          .add("attrs", attrs)
1✔
824
          .add("customOptions", Arrays.deepToString(customOptions))
1✔
825
          .toString();
1✔
826
    }
827

828
    @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
829
    public static final class Builder {
830

831
      private List<EquivalentAddressGroup> addrs;
832
      private Attributes attrs = Attributes.EMPTY;
1✔
833
      private Object[][] customOptions = new Object[0][2];
1✔
834

835
      Builder() {
1✔
836
      }
1✔
837

838
      private Builder copyCustomOptions(Object[][] options) {
839
        customOptions = new Object[options.length][2];
1✔
840
        System.arraycopy(options, 0, customOptions, 0, options.length);
1✔
841
        return this;
1✔
842
      }
843

844
      /**
845
       * Add a custom option. Any existing value for the key is overwritten.
846
       *
847
       * <p>This is an <strong>optional</strong> property.
848
       *
849
       * @param key the option key
850
       * @param value the option value
851
       */
852
      public <T> Builder addOption(Key<T> key, T value) {
853
        Preconditions.checkNotNull(key, "key");
1✔
854
        Preconditions.checkNotNull(value, "value");
1✔
855

856
        int existingIdx = -1;
1✔
857
        for (int i = 0; i < customOptions.length; i++) {
1✔
858
          if (key.equals(customOptions[i][0])) {
1✔
859
            existingIdx = i;
1✔
860
            break;
1✔
861
          }
862
        }
863

864
        if (existingIdx == -1) {
1✔
865
          Object[][] newCustomOptions = new Object[customOptions.length + 1][2];
1✔
866
          System.arraycopy(customOptions, 0, newCustomOptions, 0, customOptions.length);
1✔
867
          customOptions = newCustomOptions;
1✔
868
          existingIdx = customOptions.length - 1;
1✔
869
        }
870
        customOptions[existingIdx] = new Object[]{key, value};
1✔
871
        return this;
1✔
872
      }
873

874
      /**
875
       * The addresses to connect to.  All addresses are considered equivalent and will be tried
876
       * in the order they are provided.
877
       */
878
      public Builder setAddresses(EquivalentAddressGroup addrs) {
879
        this.addrs = Collections.singletonList(addrs);
1✔
880
        return this;
1✔
881
      }
882

883
      /**
884
       * The addresses to connect to.  All addresses are considered equivalent and will
885
       * be tried in the order they are provided.
886
       *
887
       * <p>This is a <strong>required</strong> property.
888
       *
889
       * @throws IllegalArgumentException if {@code addrs} is empty
890
       */
891
      public Builder setAddresses(List<EquivalentAddressGroup> addrs) {
892
        checkArgument(!addrs.isEmpty(), "addrs is empty");
1✔
893
        this.addrs = Collections.unmodifiableList(new ArrayList<>(addrs));
1✔
894
        return this;
1✔
895
      }
896

897
      /**
898
       * Attributes provided here will be included in {@link Subchannel#getAttributes}.
899
       *
900
       * <p>This is an <strong>optional</strong> property.  Default is empty if not set.
901
       */
902
      public Builder setAttributes(Attributes attrs) {
903
        this.attrs = checkNotNull(attrs, "attrs");
1✔
904
        return this;
1✔
905
      }
906

907
      /**
908
       * Creates a new args object.
909
       */
910
      public CreateSubchannelArgs build() {
911
        return new CreateSubchannelArgs(addrs, attrs, customOptions);
1✔
912
      }
913
    }
914

915
    /**
916
     * Key for a key-value pair. Uses reference equality.
917
     */
918
    @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
919
    public static final class Key<T> {
920

921
      private final String debugString;
922
      private final T defaultValue;
923

924
      private Key(String debugString, T defaultValue) {
1✔
925
        this.debugString = debugString;
1✔
926
        this.defaultValue = defaultValue;
1✔
927
      }
1✔
928

929
      /**
930
       * Factory method for creating instances of {@link Key}. The default value of the key is
931
       * {@code null}.
932
       *
933
       * @param debugString a debug string that describes this key.
934
       * @param <T> Key type
935
       * @return Key object
936
       */
937
      public static <T> Key<T> create(String debugString) {
938
        Preconditions.checkNotNull(debugString, "debugString");
1✔
939
        return new Key<>(debugString, /*defaultValue=*/ null);
1✔
940
      }
941

942
      /**
943
       * Factory method for creating instances of {@link Key}.
944
       *
945
       * @param debugString a debug string that describes this key.
946
       * @param defaultValue default value to return when value for key not set
947
       * @param <T> Key type
948
       * @return Key object
949
       */
950
      public static <T> Key<T> createWithDefault(String debugString, T defaultValue) {
951
        Preconditions.checkNotNull(debugString, "debugString");
1✔
952
        return new Key<>(debugString, defaultValue);
1✔
953
      }
954

955
      /**
956
       * Returns the user supplied default value for this key.
957
       */
958
      public T getDefault() {
959
        return defaultValue;
×
960
      }
961

962
      @Override
963
      public String toString() {
964
        return debugString;
1✔
965
      }
966
    }
967
  }
968

969
  /**
970
   * Provides essentials for LoadBalancer implementations.
971
   *
972
   * @since 1.2.0
973
   */
974
  @ThreadSafe
975
  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
976
  public abstract static class Helper {
1✔
977
    /**
978
     * Creates a Subchannel, which is a logical connection to the given group of addresses which are
979
     * considered equivalent.  The {@code attrs} are custom attributes associated with this
980
     * Subchannel, and can be accessed later through {@link Subchannel#getAttributes
981
     * Subchannel.getAttributes()}.
982
     *
983
     * <p>The LoadBalancer is responsible for closing unused Subchannels, and closing all
984
     * Subchannels within {@link #shutdown}.
985
     *
986
     * <p>It must be called from {@link #getSynchronizationContext the Synchronization Context}
987
     *
988
     * @return Must return a valid Subchannel object, may not return null.
989
     *
990
     * @since 1.22.0
991
     */
992
    public Subchannel createSubchannel(CreateSubchannelArgs args) {
993
      throw new UnsupportedOperationException();
1✔
994
    }
995

996
    /**
997
     * Out-of-band channel for LoadBalancer’s own RPC needs, e.g., talking to an external
998
     * load-balancer service.
999
     *
1000
     * <p>The LoadBalancer is responsible for closing unused OOB channels, and closing all OOB
1001
     * channels within {@link #shutdown}.
1002
     *
1003
     * @since 1.4.0
1004
     */
1005
    public abstract ManagedChannel createOobChannel(EquivalentAddressGroup eag, String authority);
1006

1007
    /**
1008
     * Accept a list of EAG for multiple authorities: https://github.com/grpc/grpc-java/issues/4618
1009
     * */
1010
    public ManagedChannel createOobChannel(List<EquivalentAddressGroup> eag,
1011
        String authority) {
1012
      throw new UnsupportedOperationException();
×
1013
    }
1014

1015
    /**
1016
     * Updates the addresses used for connections in the {@code Channel} that was created by {@link
1017
     * #createOobChannel(EquivalentAddressGroup, String)}. This is superior to {@link
1018
     * #createOobChannel(EquivalentAddressGroup, String)} when the old and new addresses overlap,
1019
     * since the channel can continue using an existing connection.
1020
     *
1021
     * @throws IllegalArgumentException if {@code channel} was not returned from {@link
1022
     *     #createOobChannel}
1023
     * @since 1.4.0
1024
     */
1025
    public void updateOobChannelAddresses(ManagedChannel channel, EquivalentAddressGroup eag) {
1026
      throw new UnsupportedOperationException();
×
1027
    }
1028

1029
    /**
1030
     * Updates the addresses with a new EAG list. Connection is continued when old and new addresses
1031
     * overlap.
1032
     * */
1033
    public void updateOobChannelAddresses(ManagedChannel channel,
1034
        List<EquivalentAddressGroup> eag) {
1035
      throw new UnsupportedOperationException();
×
1036
    }
1037

1038
    /**
1039
     * Creates an out-of-band channel for LoadBalancer's own RPC needs, e.g., talking to an external
1040
     * load-balancer service, that is specified by a target string.  See the documentation on
1041
     * {@link ManagedChannelBuilder#forTarget} for the format of a target string.
1042
     *
1043
     * <p>The target string will be resolved by a {@link NameResolver} created according to the
1044
     * target string.
1045
     *
1046
     * <p>The LoadBalancer is responsible for closing unused OOB channels, and closing all OOB
1047
     * channels within {@link #shutdown}.
1048
     *
1049
     * @since 1.20.0
1050
     */
1051
    public ManagedChannel createResolvingOobChannel(String target) {
1052
      return createResolvingOobChannelBuilder(target).build();
1✔
1053
    }
1054

1055
    /**
1056
     * Creates an out-of-band channel builder for LoadBalancer's own RPC needs, e.g., talking to an
1057
     * external load-balancer service, that is specified by a target string.  See the documentation
1058
     * on {@link ManagedChannelBuilder#forTarget} for the format of a target string.
1059
     *
1060
     * <p>The target string will be resolved by a {@link NameResolver} created according to the
1061
     * target string.
1062
     *
1063
     * <p>The returned oob-channel builder defaults to use the same authority and ChannelCredentials
1064
     * (without bearer tokens) as the parent channel's for authentication. This is different from
1065
     * {@link #createResolvingOobChannelBuilder(String, ChannelCredentials)}.
1066
     *
1067
     * <p>The LoadBalancer is responsible for closing unused OOB channels, and closing all OOB
1068
     * channels within {@link #shutdown}.
1069
     *
1070
     * @deprecated Use {@link #createResolvingOobChannelBuilder(String, ChannelCredentials)}
1071
     *     instead.
1072
     * @since 1.31.0
1073
     */
1074
    @Deprecated
1075
    public ManagedChannelBuilder<?> createResolvingOobChannelBuilder(String target) {
1076
      throw new UnsupportedOperationException("Not implemented");
×
1077
    }
1078

1079
    /**
1080
     * Creates an out-of-band channel builder for LoadBalancer's own RPC needs, e.g., talking to an
1081
     * external load-balancer service, that is specified by a target string and credentials.  See
1082
     * the documentation on {@link Grpc#newChannelBuilder} for the format of a target string.
1083
     *
1084
     * <p>The target string will be resolved by a {@link NameResolver} created according to the
1085
     * target string.
1086
     *
1087
     * <p>The LoadBalancer is responsible for closing unused OOB channels, and closing all OOB
1088
     * channels within {@link #shutdown}.
1089
     *
1090
     * @since 1.35.0
1091
     */
1092
    public ManagedChannelBuilder<?> createResolvingOobChannelBuilder(
1093
        String target, ChannelCredentials creds) {
1094
      throw new UnsupportedOperationException();
×
1095
    }
1096

1097
    /**
1098
     * Set a new state with a new picker to the channel.
1099
     *
1100
     * <p>When a new picker is provided via {@code updateBalancingState()}, the channel will apply
1101
     * the picker on all buffered RPCs, by calling {@link SubchannelPicker#pickSubchannel(
1102
     * LoadBalancer.PickSubchannelArgs)}.
1103
     *
1104
     * <p>The channel will hold the picker and use it for all RPCs, until {@code
1105
     * updateBalancingState()} is called again and a new picker replaces the old one.  If {@code
1106
     * updateBalancingState()} has never been called, the channel will buffer all RPCs until a
1107
     * picker is provided.
1108
     *
1109
     * <p>It should be called from the Synchronization Context.  Currently will log a warning if
1110
     * violated.  It will become an exception eventually.  See <a
1111
     * href="https://github.com/grpc/grpc-java/issues/5015">#5015</a> for the background.
1112
     *
1113
     * <p>The passed state will be the channel's new state. The SHUTDOWN state should not be passed
1114
     * and its behavior is undefined.
1115
     *
1116
     * @since 1.6.0
1117
     */
1118
    public abstract void updateBalancingState(
1119
        @Nonnull ConnectivityState newState, @Nonnull SubchannelPicker newPicker);
1120

1121
    /**
1122
     * Call {@link NameResolver#refresh} on the channel's resolver.
1123
     *
1124
     * <p>It should be called from the Synchronization Context.  Currently will log a warning if
1125
     * violated.  It will become an exception eventually.  See <a
1126
     * href="https://github.com/grpc/grpc-java/issues/5015">#5015</a> for the background.
1127
     *
1128
     * @since 1.18.0
1129
     */
1130
    public void refreshNameResolution() {
1131
      throw new UnsupportedOperationException();
×
1132
    }
1133

1134
    /**
1135
     * Historically the channel automatically refreshes name resolution if any subchannel
1136
     * connection is broken. It's transitioning to let load balancers make the decision. To
1137
     * avoid silent breakages, the channel checks if {@link #refreshNameResolution} is called
1138
     * by the load balancer. If not, it will do it and log a warning. This will be removed in
1139
     * the future and load balancers are completely responsible for triggering the refresh.
1140
     * See <a href="https://github.com/grpc/grpc-java/issues/8088">#8088</a> for the background.
1141
     *
1142
     * <p>This should rarely be used, but sometimes the address for the subchannel wasn't
1143
     * provided by the name resolver and a refresh needs to be directed somewhere else instead.
1144
     * Then you can call this method to disable the short-tem check for detecting LoadBalancers
1145
     * that need to be updated for the new expected behavior.
1146
     *
1147
     * @since 1.38.0
1148
     * @deprecated Warning has been removed
1149
     */
1150
    @ExperimentalApi("https://github.com/grpc/grpc-java/issues/8088")
1151
    @Deprecated
1152
    public void ignoreRefreshNameResolutionCheck() {
1153
      // no-op
1154
    }
×
1155

1156
    /**
1157
     * Returns a {@link SynchronizationContext} that runs tasks in the same Synchronization Context
1158
     * as that the callback methods on the {@link LoadBalancer} interface are run in.
1159
     *
1160
     * <p>Pro-tip: in order to call {@link SynchronizationContext#schedule}, you need to provide a
1161
     * {@link ScheduledExecutorService}.  {@link #getScheduledExecutorService} is provided for your
1162
     * convenience.
1163
     *
1164
     * @since 1.17.0
1165
     */
1166
    public SynchronizationContext getSynchronizationContext() {
1167
      // TODO(zhangkun): make getSynchronizationContext() abstract after runSerialized() is deleted
1168
      throw new UnsupportedOperationException();
×
1169
    }
1170

1171
    /**
1172
     * Returns a {@link ScheduledExecutorService} for scheduling delayed tasks.
1173
     *
1174
     * <p>This service is a shared resource and is only meant for quick tasks.  DO NOT block or run
1175
     * time-consuming tasks.
1176
     *
1177
     * <p>The returned service doesn't support {@link ScheduledExecutorService#shutdown shutdown()}
1178
     * and {@link ScheduledExecutorService#shutdownNow shutdownNow()}.  They will throw if called.
1179
     *
1180
     * @since 1.17.0
1181
     */
1182
    public ScheduledExecutorService getScheduledExecutorService() {
1183
      throw new UnsupportedOperationException();
×
1184
    }
1185

1186
    /**
1187
     * Returns the authority string of the channel, which is derived from the DNS-style target name.
1188
     * If overridden by a load balancer, {@link #getUnsafeChannelCredentials} must also be
1189
     * overridden to call {@link #getChannelCredentials} or provide appropriate credentials.
1190
     *
1191
     * @since 1.2.0
1192
     */
1193
    public abstract String getAuthority();
1194

1195
    /**
1196
     * Returns the target string of the channel, guaranteed to include its scheme.
1197
     */
1198
    public String getChannelTarget() {
1199
      throw new UnsupportedOperationException();
×
1200
    }
1201

1202
    /**
1203
     * Returns the ChannelCredentials used to construct the channel, without bearer tokens.
1204
     *
1205
     * @since 1.35.0
1206
     */
1207
    public ChannelCredentials getChannelCredentials() {
1208
      return getUnsafeChannelCredentials().withoutBearerTokens();
×
1209
    }
1210

1211
    /**
1212
     * Returns the UNSAFE ChannelCredentials used to construct the channel,
1213
     * including bearer tokens. Load balancers should generally have no use for
1214
     * these credentials and use of them is heavily discouraged. These must be used
1215
     * <em>very</em> carefully to avoid sending bearer tokens to untrusted servers
1216
     * as the server could then impersonate the client. Generally it is only safe
1217
     * to use these credentials when communicating with the backend.
1218
     *
1219
     * @since 1.35.0
1220
     */
1221
    public ChannelCredentials getUnsafeChannelCredentials() {
1222
      throw new UnsupportedOperationException();
×
1223
    }
1224

1225
    /**
1226
     * Returns the {@link ChannelLogger} for the Channel served by this LoadBalancer.
1227
     *
1228
     * @since 1.17.0
1229
     */
1230
    public ChannelLogger getChannelLogger() {
1231
      throw new UnsupportedOperationException();
×
1232
    }
1233

1234
    /**
1235
     * Returns the {@link NameResolver.Args} that the Channel uses to create {@link NameResolver}s.
1236
     *
1237
     * @since 1.22.0
1238
     */
1239
    public NameResolver.Args getNameResolverArgs() {
1240
      throw new UnsupportedOperationException();
×
1241
    }
1242

1243
    /**
1244
     * Returns the {@link NameResolverRegistry} that the Channel uses to look for {@link
1245
     * NameResolver}s.
1246
     *
1247
     * @since 1.22.0
1248
     */
1249
    public NameResolverRegistry getNameResolverRegistry() {
1250
      throw new UnsupportedOperationException();
×
1251
    }
1252

1253
    /**
1254
     * Returns the {@link MetricRecorder} that the channel uses to record metrics.
1255
     *
1256
     * @since 1.64.0
1257
     */
1258
    @Internal
1259
    public MetricRecorder getMetricRecorder() {
1260
      return new MetricRecorder() {};
×
1261
    }
1262
  }
1263

1264
  /**
1265
   * A logical connection to a server, or a group of equivalent servers represented by an {@link 
1266
   * EquivalentAddressGroup}.
1267
   *
1268
   * <p>It maintains at most one physical connection (aka transport) for sending new RPCs, while
1269
   * also keeps track of previous transports that has been shut down but not terminated yet.
1270
   *
1271
   * <p>If there isn't an active transport yet, and an RPC is assigned to the Subchannel, it will
1272
   * create a new transport.  It won't actively create transports otherwise.  {@link
1273
   * #requestConnection requestConnection()} can be used to ask Subchannel to create a transport if
1274
   * there isn't any.
1275
   *
1276
   * <p>{@link #start} must be called prior to calling any other methods, with the exception of
1277
   * {@link #shutdown}, which can be called at any time.
1278
   *
1279
   * @since 1.2.0
1280
   */
1281
  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
1282
  public abstract static class Subchannel {
1✔
1283
    /**
1284
     * Starts the Subchannel.  Can only be called once.
1285
     *
1286
     * <p>Must be called prior to any other method on this class, except for {@link #shutdown} which
1287
     * may be called at any time.
1288
     *
1289
     * <p>Must be called from the {@link Helper#getSynchronizationContext Synchronization Context},
1290
     * otherwise it may throw.  See <a href="https://github.com/grpc/grpc-java/issues/5015">
1291
     * #5015</a> for more discussions.
1292
     *
1293
     * @param listener receives state updates for this Subchannel.
1294
     */
1295
    public void start(SubchannelStateListener listener) {
1296
      throw new UnsupportedOperationException("Not implemented");
×
1297
    }
1298

1299
    /**
1300
     * Shuts down the Subchannel.  After this method is called, this Subchannel should no longer
1301
     * be returned by the latest {@link SubchannelPicker picker}, and can be safely discarded.
1302
     *
1303
     * <p>Calling it on an already shut-down Subchannel has no effect.
1304
     *
1305
     * <p>It should be called from the Synchronization Context.  Currently will log a warning if
1306
     * violated.  It will become an exception eventually.  See <a
1307
     * href="https://github.com/grpc/grpc-java/issues/5015">#5015</a> for the background.
1308
     *
1309
     * @since 1.2.0
1310
     */
1311
    public abstract void shutdown();
1312

1313
    /**
1314
     * Asks the Subchannel to create a connection (aka transport), if there isn't an active one.
1315
     *
1316
     * <p>It should be called from the Synchronization Context.  Currently will log a warning if
1317
     * violated.  It will become an exception eventually.  See <a
1318
     * href="https://github.com/grpc/grpc-java/issues/5015">#5015</a> for the background.
1319
     *
1320
     * @since 1.2.0
1321
     */
1322
    public abstract void requestConnection();
1323

1324
    /**
1325
     * Returns the addresses that this Subchannel is bound to.  This can be called only if
1326
     * the Subchannel has only one {@link EquivalentAddressGroup}.  Under the hood it calls
1327
     * {@link #getAllAddresses}.
1328
     *
1329
     * <p>It should be called from the Synchronization Context.  Currently will log a warning if
1330
     * violated.  It will become an exception eventually.  See <a
1331
     * href="https://github.com/grpc/grpc-java/issues/5015">#5015</a> for the background.
1332
     *
1333
     * @throws IllegalStateException if this subchannel has more than one EquivalentAddressGroup.
1334
     *         Use {@link #getAllAddresses} instead
1335
     * @since 1.2.0
1336
     */
1337
    public final EquivalentAddressGroup getAddresses() {
1338
      List<EquivalentAddressGroup> groups = getAllAddresses();
1✔
1339
      Preconditions.checkState(groups != null && groups.size() == 1,
1✔
1340
          "%s does not have exactly one group", groups);
1341
      return groups.get(0);
1✔
1342
    }
1343

1344
    /**
1345
     * Returns the addresses that this Subchannel is bound to. The returned list will not be empty.
1346
     *
1347
     * <p>It should be called from the Synchronization Context.  Currently will log a warning if
1348
     * violated.  It will become an exception eventually.  See <a
1349
     * href="https://github.com/grpc/grpc-java/issues/5015">#5015</a> for the background.
1350
     *
1351
     * @since 1.14.0
1352
     */
1353
    public List<EquivalentAddressGroup> getAllAddresses() {
1354
      throw new UnsupportedOperationException();
×
1355
    }
1356

1357
    /**
1358
     * The same attributes passed to {@link Helper#createSubchannel Helper.createSubchannel()}.
1359
     * LoadBalancer can use it to attach additional information here, e.g., the shard this
1360
     * Subchannel belongs to.
1361
     *
1362
     * @since 1.2.0
1363
     */
1364
    public abstract Attributes getAttributes();
1365

1366
    /**
1367
     * (Internal use only) returns a {@link Channel} that is backed by this Subchannel.  This allows
1368
     * a LoadBalancer to issue its own RPCs for auxiliary purposes, such as health-checking, on
1369
     * already-established connections.  This channel has certain restrictions:
1370
     * <ol>
1371
     *   <li>It can issue RPCs only if the Subchannel is {@code READY}. If {@link
1372
     *   Channel#newCall} is called when the Subchannel is not {@code READY}, the RPC will fail
1373
     *   immediately.</li>
1374
     *   <li>It doesn't support {@link CallOptions#withWaitForReady wait-for-ready} RPCs. Such RPCs
1375
     *   will fail immediately.</li>
1376
     * </ol>
1377
     *
1378
     * <p>RPCs made on this Channel is not counted when determining ManagedChannel's {@link
1379
     * ManagedChannelBuilder#idleTimeout idle mode}.  In other words, they won't prevent
1380
     * ManagedChannel from entering idle mode.
1381
     *
1382
     * <p>Warning: RPCs made on this channel will prevent a shut-down transport from terminating. If
1383
     * you make long-running RPCs, you need to make sure they will finish in time after the
1384
     * Subchannel has transitioned away from {@code READY} state
1385
     * (notified through {@link #handleSubchannelState}).
1386
     *
1387
     * <p>Warning: this is INTERNAL API, is not supposed to be used by external users, and may
1388
     * change without notice. If you think you must use it, please file an issue.
1389
     */
1390
    @Internal
1391
    public Channel asChannel() {
1392
      throw new UnsupportedOperationException();
×
1393
    }
1394

1395
    /**
1396
     * Returns a {@link ChannelLogger} for this Subchannel.
1397
     *
1398
     * @since 1.17.0
1399
     */
1400
    public ChannelLogger getChannelLogger() {
1401
      throw new UnsupportedOperationException();
×
1402
    }
1403

1404
    /**
1405
     * Replaces the existing addresses used with this {@code Subchannel}. If the new and old
1406
     * addresses overlap, the Subchannel can continue using an existing connection.
1407
     *
1408
     * <p>It must be called from the Synchronization Context or will throw.
1409
     *
1410
     * @throws IllegalArgumentException if {@code addrs} is empty
1411
     * @since 1.22.0
1412
     */
1413
    public void updateAddresses(List<EquivalentAddressGroup> addrs) {
1414
      throw new UnsupportedOperationException();
×
1415
    }
1416

1417
    /**
1418
     * (Internal use only) returns an object that represents the underlying subchannel that is used
1419
     * by the Channel for sending RPCs when this {@link Subchannel} is picked.  This is an opaque
1420
     * object that is both provided and consumed by the Channel.  Its type <strong>is not</strong>
1421
     * {@code Subchannel}.
1422
     *
1423
     * <p>Warning: this is INTERNAL API, is not supposed to be used by external users, and may
1424
     * change without notice. If you think you must use it, please file an issue and we can consider
1425
     * removing its "internal" status.
1426
     */
1427
    @Internal
1428
    public Object getInternalSubchannel() {
1429
      throw new UnsupportedOperationException();
×
1430
    }
1431

1432
    /**
1433
     * (Internal use only) returns attributes of the address subchannel is connected to.
1434
     *
1435
     * <p>Warning: this is INTERNAL API, is not supposed to be used by external users, and may
1436
     * change without notice. If you think you must use it, please file an issue and we can consider
1437
     * removing its "internal" status.
1438
     */
1439
    @Internal
1440
    public Attributes getConnectedAddressAttributes() {
1441
      throw new UnsupportedOperationException();
×
1442
    }
1443
  }
1444

1445
  /**
1446
   * Receives state changes for one {@link Subchannel}. All methods are run under {@link
1447
   * Helper#getSynchronizationContext}.
1448
   *
1449
   * @since 1.22.0
1450
   */
1451
  public interface SubchannelStateListener {
1452
    /**
1453
     * Handles a state change on a Subchannel.
1454
     *
1455
     * <p>The initial state of a Subchannel is IDLE. You won't get a notification for the initial
1456
     * IDLE state.
1457
     *
1458
     * <p>If the new state is not SHUTDOWN, this method should create a new picker and call {@link
1459
     * Helper#updateBalancingState Helper.updateBalancingState()}.  Failing to do so may result in
1460
     * unnecessary delays of RPCs. Please refer to {@link PickResult#withSubchannel
1461
     * PickResult.withSubchannel()}'s javadoc for more information.
1462
     *
1463
     * <p>When a subchannel's state is IDLE or TRANSIENT_FAILURE and the address for the subchannel
1464
     * was received in {@link LoadBalancer#handleResolvedAddresses}, load balancers should call
1465
     * {@link Helper#refreshNameResolution} to inform polling name resolvers that it is an
1466
     * appropriate time to refresh the addresses. Without the refresh, changes to the addresses may
1467
     * never be detected.
1468
     *
1469
     * <p>SHUTDOWN can only happen in two cases.  One is that LoadBalancer called {@link
1470
     * Subchannel#shutdown} earlier, thus it should have already discarded this Subchannel.  The
1471
     * other is that Channel is doing a {@link ManagedChannel#shutdownNow forced shutdown} or has
1472
     * already terminated, thus there won't be further requests to LoadBalancer.  Therefore, the
1473
     * LoadBalancer usually don't need to react to a SHUTDOWN state.
1474
     *
1475
     * @param newState the new state
1476
     * @since 1.22.0
1477
     */
1478
    void onSubchannelState(ConnectivityStateInfo newState);
1479
  }
1480

1481
  /**
1482
   * Factory to create {@link LoadBalancer} instance.
1483
   *
1484
   * @since 1.2.0
1485
   */
1486
  @ThreadSafe
1487
  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
1488
  public abstract static class Factory {
1✔
1489
    /**
1490
     * Creates a {@link LoadBalancer} that will be used inside a channel.
1491
     *
1492
     * @since 1.2.0
1493
     */
1494
    public abstract LoadBalancer newLoadBalancer(Helper helper);
1495
  }
1496

1497
  /**
1498
   * A picker that always returns an erring pick.
1499
   *
1500
   * @deprecated Use {@code new FixedResultPicker(PickResult.withError(error))} instead.
1501
   */
1502
  @Deprecated
1503
  public static final class ErrorPicker extends SubchannelPicker {
1504

1505
    private final Status error;
1506

1507
    public ErrorPicker(Status error) {
×
1508
      this.error = checkNotNull(error, "error");
×
1509
    }
×
1510

1511
    @Override
1512
    public PickResult pickSubchannel(PickSubchannelArgs args) {
1513
      return PickResult.withError(error);
×
1514
    }
1515

1516
    @Override
1517
    public String toString() {
1518
      return MoreObjects.toStringHelper(this)
×
1519
          .add("error", error)
×
1520
          .toString();
×
1521
    }
1522
  }
1523

1524
  /** A picker that always returns the same result. */
1525
  public static final class FixedResultPicker extends SubchannelPicker {
1526
    private final PickResult result;
1527

1528
    public FixedResultPicker(PickResult result) {
1✔
1529
      this.result = Preconditions.checkNotNull(result, "result");
1✔
1530
    }
1✔
1531

1532
    @Override
1533
    public PickResult pickSubchannel(PickSubchannelArgs args) {
1534
      return result;
1✔
1535
    }
1536

1537
    @Override
1538
    public String toString() {
1539
      return "FixedResultPicker(" + result + ")";
1✔
1540
    }
1541

1542
    @Override
1543
    public int hashCode() {
1544
      return result.hashCode();
×
1545
    }
1546

1547
    @Override
1548
    public boolean equals(Object o) {
1549
      if (!(o instanceof FixedResultPicker)) {
1✔
1550
        return false;
1✔
1551
      }
1552
      FixedResultPicker that = (FixedResultPicker) o;
1✔
1553
      return this.result.equals(that.result);
1✔
1554
    }
1555
  }
1556
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc