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

grpc / grpc-java / #19383

31 Jul 2024 08:32PM UTC coverage: 84.448% (+0.001%) from 84.447%
#19383

push

github

ejona86
xds: Stop extending RR in WRR

They share very little code, and we really don't want RoundRobinLb to be
public and non-final. Originally, WRR was expected to share much more
code with RR, and even delegated to RR at times. The delegation was
removed in 111ff60e. After dca89b25, most of the sharing has been moved
out into general-purpose tools that can be used by any LB policy.

FixedResultPicker now has equals to makes it as a EmptyPicker
replacement. RoundRobinLb still uses EmptyPicker because fixing its
tests is a larger change. OutlierDetectionLbTest was changed because
FixedResultPicker is used by PickFirstLeafLb, and now RoundRobinLb can
squelch some of its updates for ready pickers.

33265 of 39391 relevant lines covered (84.45%)

0.84 hits per line

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

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

1469
  /**
1470
   * Factory to create {@link LoadBalancer} instance.
1471
   *
1472
   * @since 1.2.0
1473
   */
1474
  @ThreadSafe
1475
  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
1476
  public abstract static class Factory {
1✔
1477
    /**
1478
     * Creates a {@link LoadBalancer} that will be used inside a channel.
1479
     *
1480
     * @since 1.2.0
1481
     */
1482
    public abstract LoadBalancer newLoadBalancer(Helper helper);
1483
  }
1484

1485
  /**
1486
   * A picker that always returns an erring pick.
1487
   *
1488
   * @deprecated Use {@code new FixedResultPicker(PickResult.withError(error))} instead.
1489
   */
1490
  @Deprecated
1491
  public static final class ErrorPicker extends SubchannelPicker {
1492

1493
    private final Status error;
1494

1495
    public ErrorPicker(Status error) {
×
1496
      this.error = checkNotNull(error, "error");
×
1497
    }
×
1498

1499
    @Override
1500
    public PickResult pickSubchannel(PickSubchannelArgs args) {
1501
      return PickResult.withError(error);
×
1502
    }
1503

1504
    @Override
1505
    public String toString() {
1506
      return MoreObjects.toStringHelper(this)
×
1507
          .add("error", error)
×
1508
          .toString();
×
1509
    }
1510
  }
1511

1512
  /** A picker that always returns the same result. */
1513
  public static final class FixedResultPicker extends SubchannelPicker {
1514
    private final PickResult result;
1515

1516
    public FixedResultPicker(PickResult result) {
1✔
1517
      this.result = Preconditions.checkNotNull(result, "result");
1✔
1518
    }
1✔
1519

1520
    @Override
1521
    public PickResult pickSubchannel(PickSubchannelArgs args) {
1522
      return result;
1✔
1523
    }
1524

1525
    @Override
1526
    public String toString() {
1527
      return "FixedResultPicker(" + result + ")";
1✔
1528
    }
1529

1530
    @Override
1531
    public int hashCode() {
1532
      return result.hashCode();
1✔
1533
    }
1534

1535
    @Override
1536
    public boolean equals(Object o) {
1537
      if (!(o instanceof FixedResultPicker)) {
1✔
1538
        return false;
×
1539
      }
1540
      FixedResultPicker that = (FixedResultPicker) o;
1✔
1541
      return this.result.equals(that.result);
1✔
1542
    }
1543
  }
1544
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc