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

grpc / grpc-java / #18912

21 Nov 2023 08:57PM UTC coverage: 88.175% (-0.06%) from 88.233%
#18912

push

github

ejona86
api: Deprecate LoadBalancer.EMPTY_PICKER

FixedResultPicker is our preferred approach.

30355 of 34426 relevant lines covered (88.17%)

0.88 hits per line

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

77.49
/../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
  /**
120
   * A picker that always returns an erring pick.
121
   *
122
   * @deprecated Use {@code new FixedResultPicker(PickResult.withNoResult())} instead.
123
   */
124
  @Deprecated
125
  public static final SubchannelPicker EMPTY_PICKER = new SubchannelPicker() {
1✔
126
    @Override
127
    public PickResult pickSubchannel(PickSubchannelArgs args) {
128
      return PickResult.withNoResult();
×
129
    }
130

131
    @Override
132
    public String toString() {
133
      return "EMPTY_PICKER";
×
134
    }
135
  };
136

137
  private int recursionCount;
138

139
  /**
140
   * Handles newly resolved server groups and metadata attributes from name resolution system.
141
   * {@code servers} contained in {@link EquivalentAddressGroup} should be considered equivalent
142
   * but may be flattened into a single list if needed.
143
   *
144
   * <p>Implementations should not modify the given {@code servers}.
145
   *
146
   * @param resolvedAddresses the resolved server addresses, attributes, and config.
147
   * @since 1.21.0
148
   */
149
  public void handleResolvedAddresses(ResolvedAddresses resolvedAddresses) {
150
    if (recursionCount++ == 0) {
1✔
151
      // Note that the information about the addresses actually being accepted will be lost
152
      // if you rely on this method for backward compatibility.
153
      acceptResolvedAddresses(resolvedAddresses);
1✔
154
    }
155
    recursionCount = 0;
1✔
156
  }
1✔
157

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

185
      return Status.OK;
1✔
186
    }
187
  }
188

189
  /**
190
   * Represents a combination of the resolved server address, associated attributes and a load
191
   * balancing policy config.  The config is from the {@link
192
   * LoadBalancerProvider#parseLoadBalancingPolicyConfig(Map)}.
193
   *
194
   * @since 1.21.0
195
   */
196
  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
197
  public static final class ResolvedAddresses {
198
    private final List<EquivalentAddressGroup> addresses;
199
    @NameResolver.ResolutionResultAttr
200
    private final Attributes attributes;
201
    @Nullable
202
    private final Object loadBalancingPolicyConfig;
203
    // Make sure to update toBuilder() below!
204

205
    private ResolvedAddresses(
206
        List<EquivalentAddressGroup> addresses,
207
        @NameResolver.ResolutionResultAttr Attributes attributes,
208
        Object loadBalancingPolicyConfig) {
1✔
209
      this.addresses =
1✔
210
          Collections.unmodifiableList(new ArrayList<>(checkNotNull(addresses, "addresses")));
1✔
211
      this.attributes = checkNotNull(attributes, "attributes");
1✔
212
      this.loadBalancingPolicyConfig = loadBalancingPolicyConfig;
1✔
213
    }
1✔
214

215
    /**
216
     * Factory for constructing a new Builder.
217
     *
218
     * @since 1.21.0
219
     */
220
    public static Builder newBuilder() {
221
      return new Builder();
1✔
222
    }
223

224
    /**
225
     * Converts this back to a builder.
226
     *
227
     * @since 1.21.0
228
     */
229
    public Builder toBuilder() {
230
      return newBuilder()
1✔
231
          .setAddresses(addresses)
1✔
232
          .setAttributes(attributes)
1✔
233
          .setLoadBalancingPolicyConfig(loadBalancingPolicyConfig);
1✔
234
    }
235

236
    /**
237
     * Gets the server addresses.
238
     *
239
     * @since 1.21.0
240
     */
241
    public List<EquivalentAddressGroup> getAddresses() {
242
      return addresses;
1✔
243
    }
244

245
    /**
246
     * Gets the attributes associated with these addresses.  If this was not previously set,
247
     * {@link Attributes#EMPTY} will be returned.
248
     *
249
     * @since 1.21.0
250
     */
251
    @NameResolver.ResolutionResultAttr
252
    public Attributes getAttributes() {
253
      return attributes;
1✔
254
    }
255

256
    /**
257
     * Gets the domain specific load balancing policy.  This is the config produced by
258
     * {@link LoadBalancerProvider#parseLoadBalancingPolicyConfig(Map)}.
259
     *
260
     * @since 1.21.0
261
     */
262
    @Nullable
263
    public Object getLoadBalancingPolicyConfig() {
264
      return loadBalancingPolicyConfig;
1✔
265
    }
266

267
    /**
268
     * Builder for {@link ResolvedAddresses}.
269
     */
270
    @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
271
    public static final class Builder {
272
      private List<EquivalentAddressGroup> addresses;
273
      @NameResolver.ResolutionResultAttr
1✔
274
      private Attributes attributes = Attributes.EMPTY;
275
      @Nullable
276
      private Object loadBalancingPolicyConfig;
277

278
      Builder() {}
1✔
279

280
      /**
281
       * Sets the addresses.  This field is required.
282
       *
283
       * @return this.
284
       */
285
      public Builder setAddresses(List<EquivalentAddressGroup> addresses) {
286
        this.addresses = addresses;
1✔
287
        return this;
1✔
288
      }
289

290
      /**
291
       * Sets the attributes.  This field is optional; if not called, {@link Attributes#EMPTY}
292
       * will be used.
293
       *
294
       * @return this.
295
       */
296
      public Builder setAttributes(@NameResolver.ResolutionResultAttr Attributes attributes) {
297
        this.attributes = attributes;
1✔
298
        return this;
1✔
299
      }
300

301
      /**
302
       * Sets the load balancing policy config. This field is optional.
303
       *
304
       * @return this.
305
       */
306
      public Builder setLoadBalancingPolicyConfig(@Nullable Object loadBalancingPolicyConfig) {
307
        this.loadBalancingPolicyConfig = loadBalancingPolicyConfig;
1✔
308
        return this;
1✔
309
      }
310

311
      /**
312
       * Constructs the {@link ResolvedAddresses}.
313
       */
314
      public ResolvedAddresses build() {
315
        return new ResolvedAddresses(addresses, attributes, loadBalancingPolicyConfig);
1✔
316
      }
317
    }
318

319
    @Override
320
    public String toString() {
321
      return MoreObjects.toStringHelper(this)
1✔
322
          .add("addresses", addresses)
1✔
323
          .add("attributes", attributes)
1✔
324
          .add("loadBalancingPolicyConfig", loadBalancingPolicyConfig)
1✔
325
          .toString();
1✔
326
    }
327

328
    @Override
329
    public int hashCode() {
330
      return Objects.hashCode(addresses, attributes, loadBalancingPolicyConfig);
×
331
    }
332

333
    @Override
334
    public boolean equals(Object obj) {
335
      if (!(obj instanceof ResolvedAddresses)) {
1✔
336
        return false;
×
337
      }
338
      ResolvedAddresses that = (ResolvedAddresses) obj;
1✔
339
      return Objects.equal(this.addresses, that.addresses)
1✔
340
          && Objects.equal(this.attributes, that.attributes)
1✔
341
          && Objects.equal(this.loadBalancingPolicyConfig, that.loadBalancingPolicyConfig);
1✔
342
    }
343
  }
344

345
  /**
346
   * Handles an error from the name resolution system.
347
   *
348
   * @param error a non-OK status
349
   * @since 1.2.0
350
   */
351
  public abstract void handleNameResolutionError(Status error);
352

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

384
  /**
385
   * The channel asks the load-balancer to shutdown.  No more methods on this class will be called
386
   * after this method.  The implementation should shutdown all Subchannels and OOB channels, and do
387
   * any other cleanup as necessary.
388
   *
389
   * @since 1.2.0
390
   */
391
  public abstract void shutdown();
392

393
  /**
394
   * Whether this LoadBalancer can handle empty address group list to be passed to {@link
395
   * #handleResolvedAddresses(ResolvedAddresses)}.  The default implementation returns
396
   * {@code false}, meaning that if the NameResolver returns an empty list, the Channel will turn
397
   * that into an error and call {@link #handleNameResolutionError}.  LoadBalancers that want to
398
   * accept empty lists should override this method and return {@code true}.
399
   *
400
   * <p>This method should always return a constant value.  It's not specified when this will be
401
   * called.
402
   */
403
  public boolean canHandleEmptyAddressListFromNameResolution() {
404
    return false;
×
405
  }
406

407
  /**
408
   * The channel asks the LoadBalancer to establish connections now (if applicable) so that the
409
   * upcoming RPC may then just pick a ready connection without waiting for connections.  This
410
   * is triggered by {@link ManagedChannel#getState ManagedChannel.getState(true)}.
411
   *
412
   * <p>If LoadBalancer doesn't override it, this is no-op.  If it infeasible to create connections
413
   * given the current state, e.g. no Subchannel has been created yet, LoadBalancer can ignore this
414
   * request.
415
   *
416
   * @since 1.22.0
417
   */
418
  public void requestConnection() {}
1✔
419

420
  /**
421
   * The main balancing logic.  It <strong>must be thread-safe</strong>. Typically it should only
422
   * synchronize on its own state, and avoid synchronizing with the LoadBalancer's state.
423
   *
424
   * @since 1.2.0
425
   */
426
  @ThreadSafe
427
  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
428
  public abstract static class SubchannelPicker {
1✔
429
    /**
430
     * Make a balancing decision for a new RPC.
431
     *
432
     * @param args the pick arguments
433
     * @since 1.3.0
434
     */
435
    public abstract PickResult pickSubchannel(PickSubchannelArgs args);
436

437
    /**
438
     * Tries to establish connections now so that the upcoming RPC may then just pick a ready
439
     * connection without having to connect first.
440
     *
441
     * <p>No-op if unsupported.
442
     *
443
     * @deprecated override {@link LoadBalancer#requestConnection} instead.
444
     * @since 1.11.0
445
     */
446
    @Deprecated
447
    public void requestConnection() {}
×
448
  }
449

450
  /**
451
   * Provides arguments for a {@link SubchannelPicker#pickSubchannel(
452
   * LoadBalancer.PickSubchannelArgs)}.
453
   *
454
   * @since 1.2.0
455
   */
456
  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
457
  public abstract static class PickSubchannelArgs {
1✔
458

459
    /**
460
     * Call options.
461
     *
462
     * @since 1.2.0
463
     */
464
    public abstract CallOptions getCallOptions();
465

466
    /**
467
     * Headers of the call. {@link SubchannelPicker#pickSubchannel} may mutate it before before
468
     * returning.
469
     *
470
     * @since 1.2.0
471
     */
472
    public abstract Metadata getHeaders();
473

474
    /**
475
     * Call method.
476
     *
477
     * @since 1.2.0
478
     */
479
    public abstract MethodDescriptor<?, ?> getMethodDescriptor();
480
  }
481

482
  /**
483
   * A balancing decision made by {@link SubchannelPicker SubchannelPicker} for an RPC.
484
   *
485
   * <p>The outcome of the decision will be one of the following:
486
   * <ul>
487
   *   <li>Proceed: if a Subchannel is provided via {@link #withSubchannel withSubchannel()}, and is
488
   *       in READY state when the RPC tries to start on it, the RPC will proceed on that
489
   *       Subchannel.</li>
490
   *   <li>Error: if an error is provided via {@link #withError withError()}, and the RPC is not
491
   *       wait-for-ready (i.e., {@link CallOptions#withWaitForReady} was not called), the RPC will
492
   *       fail immediately with the given error.</li>
493
   *   <li>Buffer: in all other cases, the RPC will be buffered in the Channel, until the next
494
   *       picker is provided via {@link Helper#updateBalancingState Helper.updateBalancingState()},
495
   *       when the RPC will go through the same picking process again.</li>
496
   * </ul>
497
   *
498
   * @since 1.2.0
499
   */
500
  @Immutable
501
  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
502
  public static final class PickResult {
503
    private static final PickResult NO_RESULT = new PickResult(null, null, Status.OK, false);
1✔
504

505
    @Nullable private final Subchannel subchannel;
506
    @Nullable private final ClientStreamTracer.Factory streamTracerFactory;
507
    // An error to be propagated to the application if subchannel == null
508
    // Or OK if there is no error.
509
    // subchannel being null and error being OK means RPC needs to wait
510
    private final Status status;
511
    // True if the result is created by withDrop()
512
    private final boolean drop;
513

514
    private PickResult(
515
        @Nullable Subchannel subchannel, @Nullable ClientStreamTracer.Factory streamTracerFactory,
516
        Status status, boolean drop) {
1✔
517
      this.subchannel = subchannel;
1✔
518
      this.streamTracerFactory = streamTracerFactory;
1✔
519
      this.status = checkNotNull(status, "status");
1✔
520
      this.drop = drop;
1✔
521
    }
1✔
522

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

600
    /**
601
     * Equivalent to {@code withSubchannel(subchannel, null)}.
602
     *
603
     * @since 1.2.0
604
     */
605
    public static PickResult withSubchannel(Subchannel subchannel) {
606
      return withSubchannel(subchannel, null);
1✔
607
    }
608

609
    /**
610
     * A decision to report a connectivity error to the RPC.  If the RPC is {@link
611
     * CallOptions#withWaitForReady wait-for-ready}, it will stay buffered.  Otherwise, it will fail
612
     * with the given error.
613
     *
614
     * @param error the error status.  Must not be OK.
615
     * @since 1.2.0
616
     */
617
    public static PickResult withError(Status error) {
618
      Preconditions.checkArgument(!error.isOk(), "error status shouldn't be OK");
1✔
619
      return new PickResult(null, null, error, false);
1✔
620
    }
621

622
    /**
623
     * A decision to fail an RPC immediately.  This is a final decision and will ignore retry
624
     * policy.
625
     *
626
     * @param status the status with which the RPC will fail.  Must not be OK.
627
     * @since 1.8.0
628
     */
629
    public static PickResult withDrop(Status status) {
630
      Preconditions.checkArgument(!status.isOk(), "drop status shouldn't be OK");
1✔
631
      return new PickResult(null, null, status, true);
1✔
632
    }
633

634
    /**
635
     * No decision could be made.  The RPC will stay buffered.
636
     *
637
     * @since 1.2.0
638
     */
639
    public static PickResult withNoResult() {
640
      return NO_RESULT;
1✔
641
    }
642

643
    /**
644
     * The Subchannel if this result was created by {@link #withSubchannel withSubchannel()}, or
645
     * null otherwise.
646
     *
647
     * @since 1.2.0
648
     */
649
    @Nullable
650
    public Subchannel getSubchannel() {
651
      return subchannel;
1✔
652
    }
653

654
    /**
655
     * The stream tracer factory this result was created with.
656
     *
657
     * @since 1.3.0
658
     */
659
    @Nullable
660
    public ClientStreamTracer.Factory getStreamTracerFactory() {
661
      return streamTracerFactory;
1✔
662
    }
663

664
    /**
665
     * The status associated with this result.  Non-{@code OK} if created with {@link #withError
666
     * withError}, or {@code OK} otherwise.
667
     *
668
     * @since 1.2.0
669
     */
670
    public Status getStatus() {
671
      return status;
1✔
672
    }
673

674
    /**
675
     * Returns {@code true} if this result was created by {@link #withDrop withDrop()}.
676
     *
677
     * @since 1.8.0
678
     */
679
    public boolean isDrop() {
680
      return drop;
1✔
681
    }
682

683
    @Override
684
    public String toString() {
685
      return MoreObjects.toStringHelper(this)
1✔
686
          .add("subchannel", subchannel)
1✔
687
          .add("streamTracerFactory", streamTracerFactory)
1✔
688
          .add("status", status)
1✔
689
          .add("drop", drop)
1✔
690
          .toString();
1✔
691
    }
692

693
    @Override
694
    public int hashCode() {
695
      return Objects.hashCode(subchannel, status, streamTracerFactory, drop);
×
696
    }
697

698
    /**
699
     * Returns true if the {@link Subchannel}, {@link Status}, and
700
     * {@link ClientStreamTracer.Factory} all match.
701
     */
702
    @Override
703
    public boolean equals(Object other) {
704
      if (!(other instanceof PickResult)) {
1✔
705
        return false;
×
706
      }
707
      PickResult that = (PickResult) other;
1✔
708
      return Objects.equal(subchannel, that.subchannel) && Objects.equal(status, that.status)
1✔
709
          && Objects.equal(streamTracerFactory, that.streamTracerFactory)
1✔
710
          && drop == that.drop;
711
    }
712
  }
713

714
  /**
715
   * Arguments for creating a {@link Subchannel}.
716
   *
717
   * @since 1.22.0
718
   */
719
  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
720
  public static final class CreateSubchannelArgs {
721
    private final List<EquivalentAddressGroup> addrs;
722
    private final Attributes attrs;
723
    private final Object[][] customOptions;
724

725
    private CreateSubchannelArgs(
726
        List<EquivalentAddressGroup> addrs, Attributes attrs, Object[][] customOptions) {
1✔
727
      this.addrs = checkNotNull(addrs, "addresses are not set");
1✔
728
      this.attrs = checkNotNull(attrs, "attrs");
1✔
729
      this.customOptions = checkNotNull(customOptions, "customOptions");
1✔
730
    }
1✔
731

732
    /**
733
     * Returns the addresses, which is an unmodifiable list.
734
     */
735
    public List<EquivalentAddressGroup> getAddresses() {
736
      return addrs;
1✔
737
    }
738

739
    /**
740
     * Returns the attributes.
741
     */
742
    public Attributes getAttributes() {
743
      return attrs;
1✔
744
    }
745

746
    /**
747
     * Get the value for a custom option or its inherent default.
748
     *
749
     * @param key Key identifying option
750
     */
751
    @SuppressWarnings("unchecked")
752
    public <T> T getOption(Key<T> key) {
753
      Preconditions.checkNotNull(key, "key");
1✔
754
      for (int i = 0; i < customOptions.length; i++) {
1✔
755
        if (key.equals(customOptions[i][0])) {
1✔
756
          return (T) customOptions[i][1];
1✔
757
        }
758
      }
759
      return key.defaultValue;
1✔
760
    }
761

762
    /**
763
     * Returns a builder with the same initial values as this object.
764
     */
765
    public Builder toBuilder() {
766
      return newBuilder().setAddresses(addrs).setAttributes(attrs).copyCustomOptions(customOptions);
1✔
767
    }
768

769
    /**
770
     * Creates a new builder.
771
     */
772
    public static Builder newBuilder() {
773
      return new Builder();
1✔
774
    }
775

776
    @Override
777
    public String toString() {
778
      return MoreObjects.toStringHelper(this)
1✔
779
          .add("addrs", addrs)
1✔
780
          .add("attrs", attrs)
1✔
781
          .add("customOptions", Arrays.deepToString(customOptions))
1✔
782
          .toString();
1✔
783
    }
784

785
    @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
786
    public static final class Builder {
787

788
      private List<EquivalentAddressGroup> addrs;
789
      private Attributes attrs = Attributes.EMPTY;
1✔
790
      private Object[][] customOptions = new Object[0][2];
1✔
791

792
      Builder() {
1✔
793
      }
1✔
794

795
      private Builder copyCustomOptions(Object[][] options) {
796
        customOptions = new Object[options.length][2];
1✔
797
        System.arraycopy(options, 0, customOptions, 0, options.length);
1✔
798
        return this;
1✔
799
      }
800

801
      /**
802
       * Add a custom option. Any existing value for the key is overwritten.
803
       *
804
       * <p>This is an <strong>optional</strong> property.
805
       *
806
       * @param key the option key
807
       * @param value the option value
808
       */
809
      public <T> Builder addOption(Key<T> key, T value) {
810
        Preconditions.checkNotNull(key, "key");
1✔
811
        Preconditions.checkNotNull(value, "value");
1✔
812

813
        int existingIdx = -1;
1✔
814
        for (int i = 0; i < customOptions.length; i++) {
1✔
815
          if (key.equals(customOptions[i][0])) {
1✔
816
            existingIdx = i;
1✔
817
            break;
1✔
818
          }
819
        }
820

821
        if (existingIdx == -1) {
1✔
822
          Object[][] newCustomOptions = new Object[customOptions.length + 1][2];
1✔
823
          System.arraycopy(customOptions, 0, newCustomOptions, 0, customOptions.length);
1✔
824
          customOptions = newCustomOptions;
1✔
825
          existingIdx = customOptions.length - 1;
1✔
826
        }
827
        customOptions[existingIdx] = new Object[]{key, value};
1✔
828
        return this;
1✔
829
      }
830

831
      /**
832
       * The addresses to connect to.  All addresses are considered equivalent and will be tried
833
       * in the order they are provided.
834
       */
835
      public Builder setAddresses(EquivalentAddressGroup addrs) {
836
        this.addrs = Collections.singletonList(addrs);
1✔
837
        return this;
1✔
838
      }
839

840
      /**
841
       * The addresses to connect to.  All addresses are considered equivalent and will
842
       * be tried in the order they are provided.
843
       *
844
       * <p>This is a <strong>required</strong> property.
845
       *
846
       * @throws IllegalArgumentException if {@code addrs} is empty
847
       */
848
      public Builder setAddresses(List<EquivalentAddressGroup> addrs) {
849
        checkArgument(!addrs.isEmpty(), "addrs is empty");
1✔
850
        this.addrs = Collections.unmodifiableList(new ArrayList<>(addrs));
1✔
851
        return this;
1✔
852
      }
853

854
      /**
855
       * Attributes provided here will be included in {@link Subchannel#getAttributes}.
856
       *
857
       * <p>This is an <strong>optional</strong> property.  Default is empty if not set.
858
       */
859
      public Builder setAttributes(Attributes attrs) {
860
        this.attrs = checkNotNull(attrs, "attrs");
1✔
861
        return this;
1✔
862
      }
863

864
      /**
865
       * Creates a new args object.
866
       */
867
      public CreateSubchannelArgs build() {
868
        return new CreateSubchannelArgs(addrs, attrs, customOptions);
1✔
869
      }
870
    }
871

872
    /**
873
     * Key for a key-value pair. Uses reference equality.
874
     */
875
    @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
876
    public static final class Key<T> {
877

878
      private final String debugString;
879
      private final T defaultValue;
880

881
      private Key(String debugString, T defaultValue) {
1✔
882
        this.debugString = debugString;
1✔
883
        this.defaultValue = defaultValue;
1✔
884
      }
1✔
885

886
      /**
887
       * Factory method for creating instances of {@link Key}. The default value of the key is
888
       * {@code null}.
889
       *
890
       * @param debugString a debug string that describes this key.
891
       * @param <T> Key type
892
       * @return Key object
893
       */
894
      public static <T> Key<T> create(String debugString) {
895
        Preconditions.checkNotNull(debugString, "debugString");
1✔
896
        return new Key<>(debugString, /*defaultValue=*/ null);
1✔
897
      }
898

899
      /**
900
       * Factory method for creating instances of {@link Key}.
901
       *
902
       * @param debugString a debug string that describes this key.
903
       * @param defaultValue default value to return when value for key not set
904
       * @param <T> Key type
905
       * @return Key object
906
       */
907
      public static <T> Key<T> createWithDefault(String debugString, T defaultValue) {
908
        Preconditions.checkNotNull(debugString, "debugString");
1✔
909
        return new Key<>(debugString, defaultValue);
1✔
910
      }
911

912
      /**
913
       * Returns the user supplied default value for this key.
914
       */
915
      public T getDefault() {
916
        return defaultValue;
×
917
      }
918

919
      @Override
920
      public String toString() {
921
        return debugString;
1✔
922
      }
923
    }
924
  }
925

926
  /**
927
   * Provides essentials for LoadBalancer implementations.
928
   *
929
   * @since 1.2.0
930
   */
931
  @ThreadSafe
932
  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
933
  public abstract static class Helper {
1✔
934
    /**
935
     * Creates a Subchannel, which is a logical connection to the given group of addresses which are
936
     * considered equivalent.  The {@code attrs} are custom attributes associated with this
937
     * Subchannel, and can be accessed later through {@link Subchannel#getAttributes
938
     * Subchannel.getAttributes()}.
939
     *
940
     * <p>The LoadBalancer is responsible for closing unused Subchannels, and closing all
941
     * Subchannels within {@link #shutdown}.
942
     *
943
     * <p>It must be called from {@link #getSynchronizationContext the Synchronization Context}
944
     *
945
     * @since 1.22.0
946
     */
947
    public Subchannel createSubchannel(CreateSubchannelArgs args) {
948
      throw new UnsupportedOperationException();
1✔
949
    }
950

951
    /**
952
     * Out-of-band channel for LoadBalancer’s own RPC needs, e.g., talking to an external
953
     * load-balancer service.
954
     *
955
     * <p>The LoadBalancer is responsible for closing unused OOB channels, and closing all OOB
956
     * channels within {@link #shutdown}.
957
     *
958
     * @since 1.4.0
959
     */
960
    public abstract ManagedChannel createOobChannel(EquivalentAddressGroup eag, String authority);
961

962
    /**
963
     * Accept a list of EAG for multiple authorities: https://github.com/grpc/grpc-java/issues/4618
964
     * */
965
    public ManagedChannel createOobChannel(List<EquivalentAddressGroup> eag,
966
        String authority) {
967
      throw new UnsupportedOperationException();
×
968
    }
969

970
    /**
971
     * Updates the addresses used for connections in the {@code Channel} that was created by {@link
972
     * #createOobChannel(EquivalentAddressGroup, String)}. This is superior to {@link
973
     * #createOobChannel(EquivalentAddressGroup, String)} when the old and new addresses overlap,
974
     * since the channel can continue using an existing connection.
975
     *
976
     * @throws IllegalArgumentException if {@code channel} was not returned from {@link
977
     *     #createOobChannel}
978
     * @since 1.4.0
979
     */
980
    public void updateOobChannelAddresses(ManagedChannel channel, EquivalentAddressGroup eag) {
981
      throw new UnsupportedOperationException();
×
982
    }
983

984
    /**
985
     * Updates the addresses with a new EAG list. Connection is continued when old and new addresses
986
     * overlap.
987
     * */
988
    public void updateOobChannelAddresses(ManagedChannel channel,
989
        List<EquivalentAddressGroup> eag) {
990
      throw new UnsupportedOperationException();
×
991
    }
992

993
    /**
994
     * Creates an out-of-band channel for LoadBalancer's own RPC needs, e.g., talking to an external
995
     * load-balancer service, that is specified by a target string.  See the documentation on
996
     * {@link ManagedChannelBuilder#forTarget} for the format of a target string.
997
     *
998
     * <p>The target string will be resolved by a {@link NameResolver} created according to the
999
     * target string.
1000
     *
1001
     * <p>The LoadBalancer is responsible for closing unused OOB channels, and closing all OOB
1002
     * channels within {@link #shutdown}.
1003
     *
1004
     * @since 1.20.0
1005
     */
1006
    public ManagedChannel createResolvingOobChannel(String target) {
1007
      return createResolvingOobChannelBuilder(target).build();
1✔
1008
    }
1009

1010
    /**
1011
     * Creates an out-of-band channel builder for LoadBalancer's own RPC needs, e.g., talking to an
1012
     * external load-balancer service, that is specified by a target string.  See the documentation
1013
     * on {@link ManagedChannelBuilder#forTarget} for the format of a target string.
1014
     *
1015
     * <p>The target string will be resolved by a {@link NameResolver} created according to the
1016
     * target string.
1017
     *
1018
     * <p>The returned oob-channel builder defaults to use the same authority and ChannelCredentials
1019
     * (without bearer tokens) as the parent channel's for authentication. This is different from
1020
     * {@link #createResolvingOobChannelBuilder(String, ChannelCredentials)}.
1021
     *
1022
     * <p>The LoadBalancer is responsible for closing unused OOB channels, and closing all OOB
1023
     * channels within {@link #shutdown}.
1024
     *
1025
     * @deprecated Use {@link #createResolvingOobChannelBuilder(String, ChannelCredentials)}
1026
     *     instead.
1027
     * @since 1.31.0
1028
     */
1029
    @Deprecated
1030
    public ManagedChannelBuilder<?> createResolvingOobChannelBuilder(String target) {
1031
      throw new UnsupportedOperationException("Not implemented");
×
1032
    }
1033

1034
    /**
1035
     * Creates an out-of-band channel builder for LoadBalancer's own RPC needs, e.g., talking to an
1036
     * external load-balancer service, that is specified by a target string and credentials.  See
1037
     * the documentation on {@link Grpc#newChannelBuilder} for the format of a target string.
1038
     *
1039
     * <p>The target string will be resolved by a {@link NameResolver} created according to the
1040
     * target string.
1041
     *
1042
     * <p>The LoadBalancer is responsible for closing unused OOB channels, and closing all OOB
1043
     * channels within {@link #shutdown}.
1044
     *
1045
     * @since 1.35.0
1046
     */
1047
    public ManagedChannelBuilder<?> createResolvingOobChannelBuilder(
1048
        String target, ChannelCredentials creds) {
1049
      throw new UnsupportedOperationException();
×
1050
    }
1051

1052
    /**
1053
     * Set a new state with a new picker to the channel.
1054
     *
1055
     * <p>When a new picker is provided via {@code updateBalancingState()}, the channel will apply
1056
     * the picker on all buffered RPCs, by calling {@link SubchannelPicker#pickSubchannel(
1057
     * LoadBalancer.PickSubchannelArgs)}.
1058
     *
1059
     * <p>The channel will hold the picker and use it for all RPCs, until {@code
1060
     * updateBalancingState()} is called again and a new picker replaces the old one.  If {@code
1061
     * updateBalancingState()} has never been called, the channel will buffer all RPCs until a
1062
     * picker is provided.
1063
     *
1064
     * <p>It should be called from the Synchronization Context.  Currently will log a warning if
1065
     * violated.  It will become an exception eventually.  See <a
1066
     * href="https://github.com/grpc/grpc-java/issues/5015">#5015</a> for the background.
1067
     *
1068
     * <p>The passed state will be the channel's new state. The SHUTDOWN state should not be passed
1069
     * and its behavior is undefined.
1070
     *
1071
     * @since 1.6.0
1072
     */
1073
    public abstract void updateBalancingState(
1074
        @Nonnull ConnectivityState newState, @Nonnull SubchannelPicker newPicker);
1075

1076
    /**
1077
     * Call {@link NameResolver#refresh} on the channel's resolver.
1078
     *
1079
     * <p>It should be called from the Synchronization Context.  Currently will log a warning if
1080
     * violated.  It will become an exception eventually.  See <a
1081
     * href="https://github.com/grpc/grpc-java/issues/5015">#5015</a> for the background.
1082
     *
1083
     * @since 1.18.0
1084
     */
1085
    public void refreshNameResolution() {
1086
      throw new UnsupportedOperationException();
×
1087
    }
1088

1089
    /**
1090
     * Historically the channel automatically refreshes name resolution if any subchannel
1091
     * connection is broken. It's transitioning to let load balancers make the decision. To
1092
     * avoid silent breakages, the channel checks if {@link #refreshNameResolution} is called
1093
     * by the load balancer. If not, it will do it and log a warning. This will be removed in
1094
     * the future and load balancers are completely responsible for triggering the refresh.
1095
     * See <a href="https://github.com/grpc/grpc-java/issues/8088">#8088</a> for the background.
1096
     *
1097
     * <p>This should rarely be used, but sometimes the address for the subchannel wasn't
1098
     * provided by the name resolver and a refresh needs to be directed somewhere else instead.
1099
     * Then you can call this method to disable the short-tem check for detecting LoadBalancers
1100
     * that need to be updated for the new expected behavior.
1101
     *
1102
     * @since 1.38.0
1103
     * @deprecated Warning has been removed
1104
     */
1105
    @ExperimentalApi("https://github.com/grpc/grpc-java/issues/8088")
1106
    @Deprecated
1107
    public void ignoreRefreshNameResolutionCheck() {
1108
      // no-op
1109
    }
×
1110

1111
    /**
1112
     * Returns a {@link SynchronizationContext} that runs tasks in the same Synchronization Context
1113
     * as that the callback methods on the {@link LoadBalancer} interface are run in.
1114
     *
1115
     * <p>Pro-tip: in order to call {@link SynchronizationContext#schedule}, you need to provide a
1116
     * {@link ScheduledExecutorService}.  {@link #getScheduledExecutorService} is provided for your
1117
     * convenience.
1118
     *
1119
     * @since 1.17.0
1120
     */
1121
    public SynchronizationContext getSynchronizationContext() {
1122
      // TODO(zhangkun): make getSynchronizationContext() abstract after runSerialized() is deleted
1123
      throw new UnsupportedOperationException();
×
1124
    }
1125

1126
    /**
1127
     * Returns a {@link ScheduledExecutorService} for scheduling delayed tasks.
1128
     *
1129
     * <p>This service is a shared resource and is only meant for quick tasks.  DO NOT block or run
1130
     * time-consuming tasks.
1131
     *
1132
     * <p>The returned service doesn't support {@link ScheduledExecutorService#shutdown shutdown()}
1133
     * and {@link ScheduledExecutorService#shutdownNow shutdownNow()}.  They will throw if called.
1134
     *
1135
     * @since 1.17.0
1136
     */
1137
    public ScheduledExecutorService getScheduledExecutorService() {
1138
      throw new UnsupportedOperationException();
×
1139
    }
1140

1141
    /**
1142
     * Returns the authority string of the channel, which is derived from the DNS-style target name.
1143
     * If overridden by a load balancer, {@link #getUnsafeChannelCredentials} must also be
1144
     * overridden to call {@link #getChannelCredentials} or provide appropriate credentials.
1145
     *
1146
     * @since 1.2.0
1147
     */
1148
    public abstract String getAuthority();
1149

1150
    /**
1151
     * Returns the ChannelCredentials used to construct the channel, without bearer tokens.
1152
     *
1153
     * @since 1.35.0
1154
     */
1155
    public ChannelCredentials getChannelCredentials() {
1156
      return getUnsafeChannelCredentials().withoutBearerTokens();
×
1157
    }
1158

1159
    /**
1160
     * Returns the UNSAFE ChannelCredentials used to construct the channel,
1161
     * including bearer tokens. Load balancers should generally have no use for
1162
     * these credentials and use of them is heavily discouraged. These must be used
1163
     * <em>very</em> carefully to avoid sending bearer tokens to untrusted servers
1164
     * as the server could then impersonate the client. Generally it is only safe
1165
     * to use these credentials when communicating with the backend.
1166
     *
1167
     * @since 1.35.0
1168
     */
1169
    public ChannelCredentials getUnsafeChannelCredentials() {
1170
      throw new UnsupportedOperationException();
×
1171
    }
1172

1173
    /**
1174
     * Returns the {@link ChannelLogger} for the Channel served by this LoadBalancer.
1175
     *
1176
     * @since 1.17.0
1177
     */
1178
    public ChannelLogger getChannelLogger() {
1179
      throw new UnsupportedOperationException();
×
1180
    }
1181

1182
    /**
1183
     * Returns the {@link NameResolver.Args} that the Channel uses to create {@link NameResolver}s.
1184
     *
1185
     * @since 1.22.0
1186
     */
1187
    public NameResolver.Args getNameResolverArgs() {
1188
      throw new UnsupportedOperationException();
×
1189
    }
1190

1191
    /**
1192
     * Returns the {@link NameResolverRegistry} that the Channel uses to look for {@link
1193
     * NameResolver}s.
1194
     *
1195
     * @since 1.22.0
1196
     */
1197
    public NameResolverRegistry getNameResolverRegistry() {
1198
      throw new UnsupportedOperationException();
×
1199
    }
1200
  }
1201

1202
  /**
1203
   * A logical connection to a server, or a group of equivalent servers represented by an {@link 
1204
   * EquivalentAddressGroup}.
1205
   *
1206
   * <p>It maintains at most one physical connection (aka transport) for sending new RPCs, while
1207
   * also keeps track of previous transports that has been shut down but not terminated yet.
1208
   *
1209
   * <p>If there isn't an active transport yet, and an RPC is assigned to the Subchannel, it will
1210
   * create a new transport.  It won't actively create transports otherwise.  {@link
1211
   * #requestConnection requestConnection()} can be used to ask Subchannel to create a transport if
1212
   * there isn't any.
1213
   *
1214
   * <p>{@link #start} must be called prior to calling any other methods, with the exception of
1215
   * {@link #shutdown}, which can be called at any time.
1216
   *
1217
   * @since 1.2.0
1218
   */
1219
  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
1220
  public abstract static class Subchannel {
1✔
1221
    /**
1222
     * Starts the Subchannel.  Can only be called once.
1223
     *
1224
     * <p>Must be called prior to any other method on this class, except for {@link #shutdown} which
1225
     * may be called at any time.
1226
     *
1227
     * <p>Must be called from the {@link Helper#getSynchronizationContext Synchronization Context},
1228
     * otherwise it may throw.  See <a href="https://github.com/grpc/grpc-java/issues/5015">
1229
     * #5015</a> for more discussions.
1230
     *
1231
     * @param listener receives state updates for this Subchannel.
1232
     */
1233
    public void start(SubchannelStateListener listener) {
1234
      throw new UnsupportedOperationException("Not implemented");
×
1235
    }
1236

1237
    /**
1238
     * Shuts down the Subchannel.  After this method is called, this Subchannel should no longer
1239
     * be returned by the latest {@link SubchannelPicker picker}, and can be safely discarded.
1240
     *
1241
     * <p>Calling it on an already shut-down Subchannel has no effect.
1242
     *
1243
     * <p>It should be called from the Synchronization Context.  Currently will log a warning if
1244
     * violated.  It will become an exception eventually.  See <a
1245
     * href="https://github.com/grpc/grpc-java/issues/5015">#5015</a> for the background.
1246
     *
1247
     * @since 1.2.0
1248
     */
1249
    public abstract void shutdown();
1250

1251
    /**
1252
     * Asks the Subchannel to create a connection (aka transport), if there isn't an active one.
1253
     *
1254
     * <p>It should be called from the Synchronization Context.  Currently will log a warning if
1255
     * violated.  It will become an exception eventually.  See <a
1256
     * href="https://github.com/grpc/grpc-java/issues/5015">#5015</a> for the background.
1257
     *
1258
     * @since 1.2.0
1259
     */
1260
    public abstract void requestConnection();
1261

1262
    /**
1263
     * Returns the addresses that this Subchannel is bound to.  This can be called only if
1264
     * the Subchannel has only one {@link EquivalentAddressGroup}.  Under the hood it calls
1265
     * {@link #getAllAddresses}.
1266
     *
1267
     * <p>It should be called from the Synchronization Context.  Currently will log a warning if
1268
     * violated.  It will become an exception eventually.  See <a
1269
     * href="https://github.com/grpc/grpc-java/issues/5015">#5015</a> for the background.
1270
     *
1271
     * @throws IllegalStateException if this subchannel has more than one EquivalentAddressGroup.
1272
     *         Use {@link #getAllAddresses} instead
1273
     * @since 1.2.0
1274
     */
1275
    public final EquivalentAddressGroup getAddresses() {
1276
      List<EquivalentAddressGroup> groups = getAllAddresses();
1✔
1277
      Preconditions.checkState(groups.size() == 1, "%s does not have exactly one group", groups);
1✔
1278
      return groups.get(0);
1✔
1279
    }
1280

1281
    /**
1282
     * Returns the addresses that this Subchannel is bound to. The returned list will not be empty.
1283
     *
1284
     * <p>It should be called from the Synchronization Context.  Currently will log a warning if
1285
     * violated.  It will become an exception eventually.  See <a
1286
     * href="https://github.com/grpc/grpc-java/issues/5015">#5015</a> for the background.
1287
     *
1288
     * @since 1.14.0
1289
     */
1290
    public List<EquivalentAddressGroup> getAllAddresses() {
1291
      throw new UnsupportedOperationException();
×
1292
    }
1293

1294
    /**
1295
     * The same attributes passed to {@link Helper#createSubchannel Helper.createSubchannel()}.
1296
     * LoadBalancer can use it to attach additional information here, e.g., the shard this
1297
     * Subchannel belongs to.
1298
     *
1299
     * @since 1.2.0
1300
     */
1301
    public abstract Attributes getAttributes();
1302

1303
    /**
1304
     * (Internal use only) returns a {@link Channel} that is backed by this Subchannel.  This allows
1305
     * a LoadBalancer to issue its own RPCs for auxiliary purposes, such as health-checking, on
1306
     * already-established connections.  This channel has certain restrictions:
1307
     * <ol>
1308
     *   <li>It can issue RPCs only if the Subchannel is {@code READY}. If {@link
1309
     *   Channel#newCall} is called when the Subchannel is not {@code READY}, the RPC will fail
1310
     *   immediately.</li>
1311
     *   <li>It doesn't support {@link CallOptions#withWaitForReady wait-for-ready} RPCs. Such RPCs
1312
     *   will fail immediately.</li>
1313
     * </ol>
1314
     *
1315
     * <p>RPCs made on this Channel is not counted when determining ManagedChannel's {@link
1316
     * ManagedChannelBuilder#idleTimeout idle mode}.  In other words, they won't prevent
1317
     * ManagedChannel from entering idle mode.
1318
     *
1319
     * <p>Warning: RPCs made on this channel will prevent a shut-down transport from terminating. If
1320
     * you make long-running RPCs, you need to make sure they will finish in time after the
1321
     * Subchannel has transitioned away from {@code READY} state
1322
     * (notified through {@link #handleSubchannelState}).
1323
     *
1324
     * <p>Warning: this is INTERNAL API, is not supposed to be used by external users, and may
1325
     * change without notice. If you think you must use it, please file an issue.
1326
     */
1327
    @Internal
1328
    public Channel asChannel() {
1329
      throw new UnsupportedOperationException();
×
1330
    }
1331

1332
    /**
1333
     * Returns a {@link ChannelLogger} for this Subchannel.
1334
     *
1335
     * @since 1.17.0
1336
     */
1337
    public ChannelLogger getChannelLogger() {
1338
      throw new UnsupportedOperationException();
×
1339
    }
1340

1341
    /**
1342
     * Replaces the existing addresses used with this {@code Subchannel}. If the new and old
1343
     * addresses overlap, the Subchannel can continue using an existing connection.
1344
     *
1345
     * <p>It must be called from the Synchronization Context or will throw.
1346
     *
1347
     * @throws IllegalArgumentException if {@code addrs} is empty
1348
     * @since 1.22.0
1349
     */
1350
    public void updateAddresses(List<EquivalentAddressGroup> addrs) {
1351
      throw new UnsupportedOperationException();
×
1352
    }
1353

1354
    /**
1355
     * (Internal use only) returns an object that represents the underlying subchannel that is used
1356
     * by the Channel for sending RPCs when this {@link Subchannel} is picked.  This is an opaque
1357
     * object that is both provided and consumed by the Channel.  Its type <strong>is not</strong>
1358
     * {@code Subchannel}.
1359
     *
1360
     * <p>Warning: this is INTERNAL API, is not supposed to be used by external users, and may
1361
     * change without notice. If you think you must use it, please file an issue and we can consider
1362
     * removing its "internal" status.
1363
     */
1364
    @Internal
1365
    public Object getInternalSubchannel() {
1366
      throw new UnsupportedOperationException();
×
1367
    }
1368
  }
1369

1370
  /**
1371
   * Receives state changes for one {@link Subchannel}. All methods are run under {@link
1372
   * Helper#getSynchronizationContext}.
1373
   *
1374
   * @since 1.22.0
1375
   */
1376
  public interface SubchannelStateListener {
1377
    /**
1378
     * Handles a state change on a Subchannel.
1379
     *
1380
     * <p>The initial state of a Subchannel is IDLE. You won't get a notification for the initial
1381
     * IDLE state.
1382
     *
1383
     * <p>If the new state is not SHUTDOWN, this method should create a new picker and call {@link
1384
     * Helper#updateBalancingState Helper.updateBalancingState()}.  Failing to do so may result in
1385
     * unnecessary delays of RPCs. Please refer to {@link PickResult#withSubchannel
1386
     * PickResult.withSubchannel()}'s javadoc for more information.
1387
     *
1388
     * <p>When a subchannel's state is IDLE or TRANSIENT_FAILURE and the address for the subchannel
1389
     * was received in {@link LoadBalancer#handleResolvedAddresses}, load balancers should call
1390
     * {@link Helper#refreshNameResolution} to inform polling name resolvers that it is an
1391
     * appropriate time to refresh the addresses. Without the refresh, changes to the addresses may
1392
     * never be detected.
1393
     *
1394
     * <p>SHUTDOWN can only happen in two cases.  One is that LoadBalancer called {@link
1395
     * Subchannel#shutdown} earlier, thus it should have already discarded this Subchannel.  The
1396
     * other is that Channel is doing a {@link ManagedChannel#shutdownNow forced shutdown} or has
1397
     * already terminated, thus there won't be further requests to LoadBalancer.  Therefore, the
1398
     * LoadBalancer usually don't need to react to a SHUTDOWN state.
1399
     *
1400
     * @param newState the new state
1401
     * @since 1.22.0
1402
     */
1403
    void onSubchannelState(ConnectivityStateInfo newState);
1404
  }
1405

1406
  /**
1407
   * Factory to create {@link LoadBalancer} instance.
1408
   *
1409
   * @since 1.2.0
1410
   */
1411
  @ThreadSafe
1412
  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
1413
  public abstract static class Factory {
1✔
1414
    /**
1415
     * Creates a {@link LoadBalancer} that will be used inside a channel.
1416
     *
1417
     * @since 1.2.0
1418
     */
1419
    public abstract LoadBalancer newLoadBalancer(Helper helper);
1420
  }
1421

1422
  /**
1423
   * A picker that always returns an erring pick.
1424
   *
1425
   * @deprecated Use {@code new FixedResultPicker(PickResult.withError(error))} instead.
1426
   */
1427
  @Deprecated
1428
  public static final class ErrorPicker extends SubchannelPicker {
1429

1430
    private final Status error;
1431

1432
    public ErrorPicker(Status error) {
×
1433
      this.error = checkNotNull(error, "error");
×
1434
    }
×
1435

1436
    @Override
1437
    public PickResult pickSubchannel(PickSubchannelArgs args) {
1438
      return PickResult.withError(error);
×
1439
    }
1440

1441
    @Override
1442
    public String toString() {
1443
      return MoreObjects.toStringHelper(this)
×
1444
          .add("error", error)
×
1445
          .toString();
×
1446
    }
1447
  }
1448

1449
  /** A picker that always returns the same result. */
1450
  public static final class FixedResultPicker extends SubchannelPicker {
1451
    private final PickResult result;
1452

1453
    public FixedResultPicker(PickResult result) {
1✔
1454
      this.result = Preconditions.checkNotNull(result, "result");
1✔
1455
    }
1✔
1456

1457
    @Override
1458
    public PickResult pickSubchannel(PickSubchannelArgs args) {
1459
      return result;
1✔
1460
    }
1461

1462
    @Override
1463
    public String toString() {
1464
      return "FixedResultPicker(" + result + ")";
1✔
1465
    }
1466
  }
1467
}
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