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

grpc / grpc-java / #19493

03 Oct 2024 12:03AM UTC coverage: 84.599% (+0.01%) from 84.586%
#19493

push

github

web-flow
Change PickFirstLeafLoadBalancer to only have 1 subchannel at a time (#11520)

* Change PickFirstLeafLoadBalancer to only have 1 subchannel at a time if environment variable GRPC_SERIALIZE_RETRIES == true.

Cache serializingRetries value so that it doesn't have to look up the flag every time.

Clear the correct task when READY in processSubchannelState and move the logic to cancelScheduledTasks

Cleanup based on PR review

remove unneeded checks for shutdown.

* Fix previously broken tests

* Shutdown previous subchannel when run off end of index.

* Provide option to disable subchannel retries to let PFLeafLB take control of retries.

* InternalSubchannel internally goes to IDLE when sees TF when reconnect is disabled.
Remove an extra index.increment in LeafLB

33705 of 39841 relevant lines covered (84.6%)

0.85 hits per line

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

76.89
/../api/src/main/java/io/grpc/LoadBalancer.java
1
/*
2
 * Copyright 2016 The gRPC Authors
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16

17
package io.grpc;
18

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

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

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

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

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

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

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

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

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

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

156
  private int recursionCount;
157

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

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

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

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

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

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

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

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

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

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

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

297
      Builder() {}
1✔
298

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

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

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

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

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

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

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

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

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

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

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

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

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

456
    /**
457
     * Tries to establish connections now so that the upcoming RPC may then just pick a ready
458
     * connection without having to connect first.
459
     *
460
     * <p>No-op if unsupported.
461
     *
462
     * @deprecated override {@link LoadBalancer#requestConnection} instead.
463
     * @since 1.11.0
464
     */
465
    @Deprecated
466
    public void requestConnection() {}
×
467
  }
468

469
  /**
470
   * Provides arguments for a {@link SubchannelPicker#pickSubchannel(
471
   * LoadBalancer.PickSubchannelArgs)}.
472
   *
473
   * @since 1.2.0
474
   */
475
  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
476
  public abstract static class PickSubchannelArgs {
1✔
477

478
    /**
479
     * Call options.
480
     *
481
     * @since 1.2.0
482
     */
483
    public abstract CallOptions getCallOptions();
484

485
    /**
486
     * Headers of the call. {@link SubchannelPicker#pickSubchannel} may mutate it before before
487
     * returning.
488
     *
489
     * @since 1.2.0
490
     */
491
    public abstract Metadata getHeaders();
492

493
    /**
494
     * Call method.
495
     *
496
     * @since 1.2.0
497
     */
498
    public abstract MethodDescriptor<?, ?> getMethodDescriptor();
499

500
    /**
501
     * Gets an object that can be informed about what sort of pick was made.
502
     */
503
    @Internal
504
    public PickDetailsConsumer getPickDetailsConsumer() {
505
      return new PickDetailsConsumer() {};
×
506
    }
507
  }
508

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

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

547
    @Nullable private final Subchannel subchannel;
548
    @Nullable private final ClientStreamTracer.Factory streamTracerFactory;
549
    // An error to be propagated to the application if subchannel == null
550
    // Or OK if there is no error.
551
    // subchannel being null and error being OK means RPC needs to wait
552
    private final Status status;
553
    // True if the result is created by withDrop()
554
    private final boolean drop;
555

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

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

642
    /**
643
     * Equivalent to {@code withSubchannel(subchannel, null)}.
644
     *
645
     * @since 1.2.0
646
     */
647
    public static PickResult withSubchannel(Subchannel subchannel) {
648
      return withSubchannel(subchannel, null);
1✔
649
    }
650

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

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

676
    /**
677
     * No decision could be made.  The RPC will stay buffered.
678
     *
679
     * @since 1.2.0
680
     */
681
    public static PickResult withNoResult() {
682
      return NO_RESULT;
1✔
683
    }
684

685
    /**
686
     * The Subchannel if this result was created by {@link #withSubchannel withSubchannel()}, or
687
     * null otherwise.
688
     *
689
     * @since 1.2.0
690
     */
691
    @Nullable
692
    public Subchannel getSubchannel() {
693
      return subchannel;
1✔
694
    }
695

696
    /**
697
     * The stream tracer factory this result was created with.
698
     *
699
     * @since 1.3.0
700
     */
701
    @Nullable
702
    public ClientStreamTracer.Factory getStreamTracerFactory() {
703
      return streamTracerFactory;
1✔
704
    }
705

706
    /**
707
     * The status associated with this result.  Non-{@code OK} if created with {@link #withError
708
     * withError}, or {@code OK} otherwise.
709
     *
710
     * @since 1.2.0
711
     */
712
    public Status getStatus() {
713
      return status;
1✔
714
    }
715

716
    /**
717
     * Returns {@code true} if this result was created by {@link #withDrop withDrop()}.
718
     *
719
     * @since 1.8.0
720
     */
721
    public boolean isDrop() {
722
      return drop;
1✔
723
    }
724

725
    /**
726
     * Returns {@code true} if the pick was not created with {@link #withNoResult()}.
727
     */
728
    public boolean hasResult() {
729
      return !(subchannel == null && status.isOk());
1✔
730
    }
731

732
    @Override
733
    public String toString() {
734
      return MoreObjects.toStringHelper(this)
1✔
735
          .add("subchannel", subchannel)
1✔
736
          .add("streamTracerFactory", streamTracerFactory)
1✔
737
          .add("status", status)
1✔
738
          .add("drop", drop)
1✔
739
          .toString();
1✔
740
    }
741

742
    @Override
743
    public int hashCode() {
744
      return Objects.hashCode(subchannel, status, streamTracerFactory, drop);
×
745
    }
746

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

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

774
    private CreateSubchannelArgs(
775
        List<EquivalentAddressGroup> addrs, Attributes attrs, Object[][] customOptions) {
1✔
776
      this.addrs = checkNotNull(addrs, "addresses are not set");
1✔
777
      this.attrs = checkNotNull(attrs, "attrs");
1✔
778
      this.customOptions = checkNotNull(customOptions, "customOptions");
1✔
779
    }
1✔
780

781
    /**
782
     * Returns the addresses, which is an unmodifiable list.
783
     */
784
    public List<EquivalentAddressGroup> getAddresses() {
785
      return addrs;
1✔
786
    }
787

788
    /**
789
     * Returns the attributes.
790
     */
791
    public Attributes getAttributes() {
792
      return attrs;
1✔
793
    }
794

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

811
    /**
812
     * Returns a builder with the same initial values as this object.
813
     */
814
    public Builder toBuilder() {
815
      return newBuilder().setAddresses(addrs).setAttributes(attrs).copyCustomOptions(customOptions);
1✔
816
    }
817

818
    /**
819
     * Creates a new builder.
820
     */
821
    public static Builder newBuilder() {
822
      return new Builder();
1✔
823
    }
824

825
    @Override
826
    public String toString() {
827
      return MoreObjects.toStringHelper(this)
1✔
828
          .add("addrs", addrs)
1✔
829
          .add("attrs", attrs)
1✔
830
          .add("customOptions", Arrays.deepToString(customOptions))
1✔
831
          .toString();
1✔
832
    }
833

834
    @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
835
    public static final class Builder {
836

837
      private List<EquivalentAddressGroup> addrs;
838
      private Attributes attrs = Attributes.EMPTY;
1✔
839
      private Object[][] customOptions = new Object[0][2];
1✔
840

841
      Builder() {
1✔
842
      }
1✔
843

844
      private Builder copyCustomOptions(Object[][] options) {
845
        customOptions = new Object[options.length][2];
1✔
846
        System.arraycopy(options, 0, customOptions, 0, options.length);
1✔
847
        return this;
1✔
848
      }
849

850
      /**
851
       * Add a custom option. Any existing value for the key is overwritten.
852
       *
853
       * <p>This is an <strong>optional</strong> property.
854
       *
855
       * @param key the option key
856
       * @param value the option value
857
       */
858
      public <T> Builder addOption(Key<T> key, T value) {
859
        Preconditions.checkNotNull(key, "key");
1✔
860
        Preconditions.checkNotNull(value, "value");
1✔
861

862
        int existingIdx = -1;
1✔
863
        for (int i = 0; i < customOptions.length; i++) {
1✔
864
          if (key.equals(customOptions[i][0])) {
1✔
865
            existingIdx = i;
1✔
866
            break;
1✔
867
          }
868
        }
869

870
        if (existingIdx == -1) {
1✔
871
          Object[][] newCustomOptions = new Object[customOptions.length + 1][2];
1✔
872
          System.arraycopy(customOptions, 0, newCustomOptions, 0, customOptions.length);
1✔
873
          customOptions = newCustomOptions;
1✔
874
          existingIdx = customOptions.length - 1;
1✔
875
        }
876
        customOptions[existingIdx] = new Object[]{key, value};
1✔
877
        return this;
1✔
878
      }
879

880
      /**
881
       * The addresses to connect to.  All addresses are considered equivalent and will be tried
882
       * in the order they are provided.
883
       */
884
      public Builder setAddresses(EquivalentAddressGroup addrs) {
885
        this.addrs = Collections.singletonList(addrs);
1✔
886
        return this;
1✔
887
      }
888

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

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

913
      /**
914
       * Creates a new args object.
915
       */
916
      public CreateSubchannelArgs build() {
917
        return new CreateSubchannelArgs(addrs, attrs, customOptions);
1✔
918
      }
919
    }
920

921
    /**
922
     * Key for a key-value pair. Uses reference equality.
923
     */
924
    @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
925
    public static final class Key<T> {
926

927
      private final String debugString;
928
      private final T defaultValue;
929

930
      private Key(String debugString, T defaultValue) {
1✔
931
        this.debugString = debugString;
1✔
932
        this.defaultValue = defaultValue;
1✔
933
      }
1✔
934

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

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

961
      /**
962
       * Returns the user supplied default value for this key.
963
       */
964
      public T getDefault() {
965
        return defaultValue;
×
966
      }
967

968
      @Override
969
      public String toString() {
970
        return debugString;
1✔
971
      }
972
    }
973
  }
974

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

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

1013
    /**
1014
     * Accept a list of EAG for multiple authorities: https://github.com/grpc/grpc-java/issues/4618
1015
     * */
1016
    public ManagedChannel createOobChannel(List<EquivalentAddressGroup> eag,
1017
        String authority) {
1018
      throw new UnsupportedOperationException();
×
1019
    }
1020

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

1035
    /**
1036
     * Updates the addresses with a new EAG list. Connection is continued when old and new addresses
1037
     * overlap.
1038
     * */
1039
    public void updateOobChannelAddresses(ManagedChannel channel,
1040
        List<EquivalentAddressGroup> eag) {
1041
      throw new UnsupportedOperationException();
×
1042
    }
1043

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

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

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

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

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

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

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

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

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

1201
    /**
1202
     * Returns the target string of the channel, guaranteed to include its scheme.
1203
     */
1204
    public String getChannelTarget() {
1205
      throw new UnsupportedOperationException();
×
1206
    }
1207

1208
    /**
1209
     * Returns the ChannelCredentials used to construct the channel, without bearer tokens.
1210
     *
1211
     * @since 1.35.0
1212
     */
1213
    public ChannelCredentials getChannelCredentials() {
1214
      return getUnsafeChannelCredentials().withoutBearerTokens();
×
1215
    }
1216

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

1231
    /**
1232
     * Returns the {@link ChannelLogger} for the Channel served by this LoadBalancer.
1233
     *
1234
     * @since 1.17.0
1235
     */
1236
    public ChannelLogger getChannelLogger() {
1237
      throw new UnsupportedOperationException();
×
1238
    }
1239

1240
    /**
1241
     * Returns the {@link NameResolver.Args} that the Channel uses to create {@link NameResolver}s.
1242
     *
1243
     * @since 1.22.0
1244
     */
1245
    public NameResolver.Args getNameResolverArgs() {
1246
      throw new UnsupportedOperationException();
×
1247
    }
1248

1249
    /**
1250
     * Returns the {@link NameResolverRegistry} that the Channel uses to look for {@link
1251
     * NameResolver}s.
1252
     *
1253
     * @since 1.22.0
1254
     */
1255
    public NameResolverRegistry getNameResolverRegistry() {
1256
      throw new UnsupportedOperationException();
×
1257
    }
1258

1259
    /**
1260
     * Returns the {@link MetricRecorder} that the channel uses to record metrics.
1261
     *
1262
     * @since 1.64.0
1263
     */
1264
    @Internal
1265
    public MetricRecorder getMetricRecorder() {
1266
      return new MetricRecorder() {};
×
1267
    }
1268
  }
1269

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

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

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

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

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

1363
    /**
1364
     * The same attributes passed to {@link Helper#createSubchannel Helper.createSubchannel()}.
1365
     * LoadBalancer can use it to attach additional information here, e.g., the shard this
1366
     * Subchannel belongs to.
1367
     *
1368
     * @since 1.2.0
1369
     */
1370
    public abstract Attributes getAttributes();
1371

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

1401
    /**
1402
     * Returns a {@link ChannelLogger} for this Subchannel.
1403
     *
1404
     * @since 1.17.0
1405
     */
1406
    public ChannelLogger getChannelLogger() {
1407
      throw new UnsupportedOperationException();
×
1408
    }
1409

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

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

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

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

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

1503
  /**
1504
   * A picker that always returns an erring pick.
1505
   *
1506
   * @deprecated Use {@code new FixedResultPicker(PickResult.withError(error))} instead.
1507
   */
1508
  @Deprecated
1509
  public static final class ErrorPicker extends SubchannelPicker {
1510

1511
    private final Status error;
1512

1513
    public ErrorPicker(Status error) {
×
1514
      this.error = checkNotNull(error, "error");
×
1515
    }
×
1516

1517
    @Override
1518
    public PickResult pickSubchannel(PickSubchannelArgs args) {
1519
      return PickResult.withError(error);
×
1520
    }
1521

1522
    @Override
1523
    public String toString() {
1524
      return MoreObjects.toStringHelper(this)
×
1525
          .add("error", error)
×
1526
          .toString();
×
1527
    }
1528
  }
1529

1530
  /** A picker that always returns the same result. */
1531
  public static final class FixedResultPicker extends SubchannelPicker {
1532
    private final PickResult result;
1533

1534
    public FixedResultPicker(PickResult result) {
1✔
1535
      this.result = Preconditions.checkNotNull(result, "result");
1✔
1536
    }
1✔
1537

1538
    @Override
1539
    public PickResult pickSubchannel(PickSubchannelArgs args) {
1540
      return result;
1✔
1541
    }
1542

1543
    @Override
1544
    public String toString() {
1545
      return "FixedResultPicker(" + result + ")";
1✔
1546
    }
1547

1548
    @Override
1549
    public int hashCode() {
1550
      return result.hashCode();
×
1551
    }
1552

1553
    @Override
1554
    public boolean equals(Object o) {
1555
      if (!(o instanceof FixedResultPicker)) {
1✔
1556
        return false;
1✔
1557
      }
1558
      FixedResultPicker that = (FixedResultPicker) o;
1✔
1559
      return this.result.equals(that.result);
1✔
1560
    }
1561
  }
1562
}
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