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

grpc / grpc-java / #19167

22 Apr 2024 02:48PM UTC coverage: 88.084% (-0.01%) from 88.096%
#19167

push

github

ejona86
util: Remove deactivation and GracefulSwitchLb from MultiChildLb

It is easy to manage these things outside of MultiChildLb and it makes
the shared code easier and use less memory. In particular, we don't want
to use many instances of GracefulSwitchLb in virtually every policy
simply because it was needed in one or two cases.

31195 of 35415 relevant lines covered (88.08%)

0.88 hits per line

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

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

17
package io.grpc;
18

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

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

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

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

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

124
  @Internal
125
  public static final Attributes.Key<Boolean>
126
      HAS_HEALTH_PRODUCER_LISTENER_KEY =
1✔
127
      Attributes.Key.create("internal:has-health-check-producer-listener");
1✔
128

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

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

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

150
  private int recursionCount;
151

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

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

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

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

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

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

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

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

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

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

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

291
      Builder() {}
1✔
292

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

518
    @Nullable private final Subchannel subchannel;
519
    @Nullable private final ClientStreamTracer.Factory streamTracerFactory;
520
    // An error to be propagated to the application if subchannel == null
521
    // Or OK if there is no error.
522
    // subchannel being null and error being OK means RPC needs to wait
523
    private final Status status;
524
    // True if the result is created by withDrop()
525
    private final boolean drop;
526

527
    private PickResult(
528
        @Nullable Subchannel subchannel, @Nullable ClientStreamTracer.Factory streamTracerFactory,
529
        Status status, boolean drop) {
1✔
530
      this.subchannel = subchannel;
1✔
531
      this.streamTracerFactory = streamTracerFactory;
1✔
532
      this.status = checkNotNull(status, "status");
1✔
533
      this.drop = drop;
1✔
534
    }
1✔
535

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

613
    /**
614
     * Equivalent to {@code withSubchannel(subchannel, null)}.
615
     *
616
     * @since 1.2.0
617
     */
618
    public static PickResult withSubchannel(Subchannel subchannel) {
619
      return withSubchannel(subchannel, null);
1✔
620
    }
621

622
    /**
623
     * A decision to report a connectivity error to the RPC.  If the RPC is {@link
624
     * CallOptions#withWaitForReady wait-for-ready}, it will stay buffered.  Otherwise, it will fail
625
     * with the given error.
626
     *
627
     * @param error the error status.  Must not be OK.
628
     * @since 1.2.0
629
     */
630
    public static PickResult withError(Status error) {
631
      Preconditions.checkArgument(!error.isOk(), "error status shouldn't be OK");
1✔
632
      return new PickResult(null, null, error, false);
1✔
633
    }
634

635
    /**
636
     * A decision to fail an RPC immediately.  This is a final decision and will ignore retry
637
     * policy.
638
     *
639
     * @param status the status with which the RPC will fail.  Must not be OK.
640
     * @since 1.8.0
641
     */
642
    public static PickResult withDrop(Status status) {
643
      Preconditions.checkArgument(!status.isOk(), "drop status shouldn't be OK");
1✔
644
      return new PickResult(null, null, status, true);
1✔
645
    }
646

647
    /**
648
     * No decision could be made.  The RPC will stay buffered.
649
     *
650
     * @since 1.2.0
651
     */
652
    public static PickResult withNoResult() {
653
      return NO_RESULT;
1✔
654
    }
655

656
    /**
657
     * The Subchannel if this result was created by {@link #withSubchannel withSubchannel()}, or
658
     * null otherwise.
659
     *
660
     * @since 1.2.0
661
     */
662
    @Nullable
663
    public Subchannel getSubchannel() {
664
      return subchannel;
1✔
665
    }
666

667
    /**
668
     * The stream tracer factory this result was created with.
669
     *
670
     * @since 1.3.0
671
     */
672
    @Nullable
673
    public ClientStreamTracer.Factory getStreamTracerFactory() {
674
      return streamTracerFactory;
1✔
675
    }
676

677
    /**
678
     * The status associated with this result.  Non-{@code OK} if created with {@link #withError
679
     * withError}, or {@code OK} otherwise.
680
     *
681
     * @since 1.2.0
682
     */
683
    public Status getStatus() {
684
      return status;
1✔
685
    }
686

687
    /**
688
     * Returns {@code true} if this result was created by {@link #withDrop withDrop()}.
689
     *
690
     * @since 1.8.0
691
     */
692
    public boolean isDrop() {
693
      return drop;
1✔
694
    }
695

696
    @Override
697
    public String toString() {
698
      return MoreObjects.toStringHelper(this)
1✔
699
          .add("subchannel", subchannel)
1✔
700
          .add("streamTracerFactory", streamTracerFactory)
1✔
701
          .add("status", status)
1✔
702
          .add("drop", drop)
1✔
703
          .toString();
1✔
704
    }
705

706
    @Override
707
    public int hashCode() {
708
      return Objects.hashCode(subchannel, status, streamTracerFactory, drop);
×
709
    }
710

711
    /**
712
     * Returns true if the {@link Subchannel}, {@link Status}, and
713
     * {@link ClientStreamTracer.Factory} all match.
714
     */
715
    @Override
716
    public boolean equals(Object other) {
717
      if (!(other instanceof PickResult)) {
1✔
718
        return false;
×
719
      }
720
      PickResult that = (PickResult) other;
1✔
721
      return Objects.equal(subchannel, that.subchannel) && Objects.equal(status, that.status)
1✔
722
          && Objects.equal(streamTracerFactory, that.streamTracerFactory)
1✔
723
          && drop == that.drop;
724
    }
725
  }
726

727
  /**
728
   * Arguments for creating a {@link Subchannel}.
729
   *
730
   * @since 1.22.0
731
   */
732
  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
733
  public static final class CreateSubchannelArgs {
734
    private final List<EquivalentAddressGroup> addrs;
735
    private final Attributes attrs;
736
    private final Object[][] customOptions;
737

738
    private CreateSubchannelArgs(
739
        List<EquivalentAddressGroup> addrs, Attributes attrs, Object[][] customOptions) {
1✔
740
      this.addrs = checkNotNull(addrs, "addresses are not set");
1✔
741
      this.attrs = checkNotNull(attrs, "attrs");
1✔
742
      this.customOptions = checkNotNull(customOptions, "customOptions");
1✔
743
    }
1✔
744

745
    /**
746
     * Returns the addresses, which is an unmodifiable list.
747
     */
748
    public List<EquivalentAddressGroup> getAddresses() {
749
      return addrs;
1✔
750
    }
751

752
    /**
753
     * Returns the attributes.
754
     */
755
    public Attributes getAttributes() {
756
      return attrs;
1✔
757
    }
758

759
    /**
760
     * Get the value for a custom option or its inherent default.
761
     *
762
     * @param key Key identifying option
763
     */
764
    @SuppressWarnings("unchecked")
765
    public <T> T getOption(Key<T> key) {
766
      Preconditions.checkNotNull(key, "key");
1✔
767
      for (int i = 0; i < customOptions.length; i++) {
1✔
768
        if (key.equals(customOptions[i][0])) {
1✔
769
          return (T) customOptions[i][1];
1✔
770
        }
771
      }
772
      return key.defaultValue;
1✔
773
    }
774

775
    /**
776
     * Returns a builder with the same initial values as this object.
777
     */
778
    public Builder toBuilder() {
779
      return newBuilder().setAddresses(addrs).setAttributes(attrs).copyCustomOptions(customOptions);
1✔
780
    }
781

782
    /**
783
     * Creates a new builder.
784
     */
785
    public static Builder newBuilder() {
786
      return new Builder();
1✔
787
    }
788

789
    @Override
790
    public String toString() {
791
      return MoreObjects.toStringHelper(this)
1✔
792
          .add("addrs", addrs)
1✔
793
          .add("attrs", attrs)
1✔
794
          .add("customOptions", Arrays.deepToString(customOptions))
1✔
795
          .toString();
1✔
796
    }
797

798
    @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
799
    public static final class Builder {
800

801
      private List<EquivalentAddressGroup> addrs;
802
      private Attributes attrs = Attributes.EMPTY;
1✔
803
      private Object[][] customOptions = new Object[0][2];
1✔
804

805
      Builder() {
1✔
806
      }
1✔
807

808
      private Builder copyCustomOptions(Object[][] options) {
809
        customOptions = new Object[options.length][2];
1✔
810
        System.arraycopy(options, 0, customOptions, 0, options.length);
1✔
811
        return this;
1✔
812
      }
813

814
      /**
815
       * Add a custom option. Any existing value for the key is overwritten.
816
       *
817
       * <p>This is an <strong>optional</strong> property.
818
       *
819
       * @param key the option key
820
       * @param value the option value
821
       */
822
      public <T> Builder addOption(Key<T> key, T value) {
823
        Preconditions.checkNotNull(key, "key");
1✔
824
        Preconditions.checkNotNull(value, "value");
1✔
825

826
        int existingIdx = -1;
1✔
827
        for (int i = 0; i < customOptions.length; i++) {
1✔
828
          if (key.equals(customOptions[i][0])) {
1✔
829
            existingIdx = i;
1✔
830
            break;
1✔
831
          }
832
        }
833

834
        if (existingIdx == -1) {
1✔
835
          Object[][] newCustomOptions = new Object[customOptions.length + 1][2];
1✔
836
          System.arraycopy(customOptions, 0, newCustomOptions, 0, customOptions.length);
1✔
837
          customOptions = newCustomOptions;
1✔
838
          existingIdx = customOptions.length - 1;
1✔
839
        }
840
        customOptions[existingIdx] = new Object[]{key, value};
1✔
841
        return this;
1✔
842
      }
843

844
      /**
845
       * The addresses to connect to.  All addresses are considered equivalent and will be tried
846
       * in the order they are provided.
847
       */
848
      public Builder setAddresses(EquivalentAddressGroup addrs) {
849
        this.addrs = Collections.singletonList(addrs);
1✔
850
        return this;
1✔
851
      }
852

853
      /**
854
       * The addresses to connect to.  All addresses are considered equivalent and will
855
       * be tried in the order they are provided.
856
       *
857
       * <p>This is a <strong>required</strong> property.
858
       *
859
       * @throws IllegalArgumentException if {@code addrs} is empty
860
       */
861
      public Builder setAddresses(List<EquivalentAddressGroup> addrs) {
862
        checkArgument(!addrs.isEmpty(), "addrs is empty");
1✔
863
        this.addrs = Collections.unmodifiableList(new ArrayList<>(addrs));
1✔
864
        return this;
1✔
865
      }
866

867
      /**
868
       * Attributes provided here will be included in {@link Subchannel#getAttributes}.
869
       *
870
       * <p>This is an <strong>optional</strong> property.  Default is empty if not set.
871
       */
872
      public Builder setAttributes(Attributes attrs) {
873
        this.attrs = checkNotNull(attrs, "attrs");
1✔
874
        return this;
1✔
875
      }
876

877
      /**
878
       * Creates a new args object.
879
       */
880
      public CreateSubchannelArgs build() {
881
        return new CreateSubchannelArgs(addrs, attrs, customOptions);
1✔
882
      }
883
    }
884

885
    /**
886
     * Key for a key-value pair. Uses reference equality.
887
     */
888
    @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
889
    public static final class Key<T> {
890

891
      private final String debugString;
892
      private final T defaultValue;
893

894
      private Key(String debugString, T defaultValue) {
1✔
895
        this.debugString = debugString;
1✔
896
        this.defaultValue = defaultValue;
1✔
897
      }
1✔
898

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

912
      /**
913
       * Factory method for creating instances of {@link Key}.
914
       *
915
       * @param debugString a debug string that describes this key.
916
       * @param defaultValue default value to return when value for key not set
917
       * @param <T> Key type
918
       * @return Key object
919
       */
920
      public static <T> Key<T> createWithDefault(String debugString, T defaultValue) {
921
        Preconditions.checkNotNull(debugString, "debugString");
1✔
922
        return new Key<>(debugString, defaultValue);
1✔
923
      }
924

925
      /**
926
       * Returns the user supplied default value for this key.
927
       */
928
      public T getDefault() {
929
        return defaultValue;
×
930
      }
931

932
      @Override
933
      public String toString() {
934
        return debugString;
1✔
935
      }
936
    }
937
  }
938

939
  /**
940
   * Provides essentials for LoadBalancer implementations.
941
   *
942
   * @since 1.2.0
943
   */
944
  @ThreadSafe
945
  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
946
  public abstract static class Helper {
1✔
947
    /**
948
     * Creates a Subchannel, which is a logical connection to the given group of addresses which are
949
     * considered equivalent.  The {@code attrs} are custom attributes associated with this
950
     * Subchannel, and can be accessed later through {@link Subchannel#getAttributes
951
     * Subchannel.getAttributes()}.
952
     *
953
     * <p>The LoadBalancer is responsible for closing unused Subchannels, and closing all
954
     * Subchannels within {@link #shutdown}.
955
     *
956
     * <p>It must be called from {@link #getSynchronizationContext the Synchronization Context}
957
     *
958
     * @return Must return a valid Subchannel object, may not return null.
959
     *
960
     * @since 1.22.0
961
     */
962
    public Subchannel createSubchannel(CreateSubchannelArgs args) {
963
      throw new UnsupportedOperationException();
1✔
964
    }
965

966
    /**
967
     * Out-of-band channel for LoadBalancer’s own RPC needs, e.g., talking to an external
968
     * load-balancer service.
969
     *
970
     * <p>The LoadBalancer is responsible for closing unused OOB channels, and closing all OOB
971
     * channels within {@link #shutdown}.
972
     *
973
     * @since 1.4.0
974
     */
975
    public abstract ManagedChannel createOobChannel(EquivalentAddressGroup eag, String authority);
976

977
    /**
978
     * Accept a list of EAG for multiple authorities: https://github.com/grpc/grpc-java/issues/4618
979
     * */
980
    public ManagedChannel createOobChannel(List<EquivalentAddressGroup> eag,
981
        String authority) {
982
      throw new UnsupportedOperationException();
×
983
    }
984

985
    /**
986
     * Updates the addresses used for connections in the {@code Channel} that was created by {@link
987
     * #createOobChannel(EquivalentAddressGroup, String)}. This is superior to {@link
988
     * #createOobChannel(EquivalentAddressGroup, String)} when the old and new addresses overlap,
989
     * since the channel can continue using an existing connection.
990
     *
991
     * @throws IllegalArgumentException if {@code channel} was not returned from {@link
992
     *     #createOobChannel}
993
     * @since 1.4.0
994
     */
995
    public void updateOobChannelAddresses(ManagedChannel channel, EquivalentAddressGroup eag) {
996
      throw new UnsupportedOperationException();
×
997
    }
998

999
    /**
1000
     * Updates the addresses with a new EAG list. Connection is continued when old and new addresses
1001
     * overlap.
1002
     * */
1003
    public void updateOobChannelAddresses(ManagedChannel channel,
1004
        List<EquivalentAddressGroup> eag) {
1005
      throw new UnsupportedOperationException();
×
1006
    }
1007

1008
    /**
1009
     * Creates an out-of-band channel for LoadBalancer's own RPC needs, e.g., talking to an external
1010
     * load-balancer service, that is specified by a target string.  See the documentation on
1011
     * {@link ManagedChannelBuilder#forTarget} for the format of a target string.
1012
     *
1013
     * <p>The target string will be resolved by a {@link NameResolver} created according to the
1014
     * target string.
1015
     *
1016
     * <p>The LoadBalancer is responsible for closing unused OOB channels, and closing all OOB
1017
     * channels within {@link #shutdown}.
1018
     *
1019
     * @since 1.20.0
1020
     */
1021
    public ManagedChannel createResolvingOobChannel(String target) {
1022
      return createResolvingOobChannelBuilder(target).build();
1✔
1023
    }
1024

1025
    /**
1026
     * Creates an out-of-band channel builder for LoadBalancer's own RPC needs, e.g., talking to an
1027
     * external load-balancer service, that is specified by a target string.  See the documentation
1028
     * on {@link ManagedChannelBuilder#forTarget} for the format of a target string.
1029
     *
1030
     * <p>The target string will be resolved by a {@link NameResolver} created according to the
1031
     * target string.
1032
     *
1033
     * <p>The returned oob-channel builder defaults to use the same authority and ChannelCredentials
1034
     * (without bearer tokens) as the parent channel's for authentication. This is different from
1035
     * {@link #createResolvingOobChannelBuilder(String, ChannelCredentials)}.
1036
     *
1037
     * <p>The LoadBalancer is responsible for closing unused OOB channels, and closing all OOB
1038
     * channels within {@link #shutdown}.
1039
     *
1040
     * @deprecated Use {@link #createResolvingOobChannelBuilder(String, ChannelCredentials)}
1041
     *     instead.
1042
     * @since 1.31.0
1043
     */
1044
    @Deprecated
1045
    public ManagedChannelBuilder<?> createResolvingOobChannelBuilder(String target) {
1046
      throw new UnsupportedOperationException("Not implemented");
×
1047
    }
1048

1049
    /**
1050
     * Creates an out-of-band channel builder for LoadBalancer's own RPC needs, e.g., talking to an
1051
     * external load-balancer service, that is specified by a target string and credentials.  See
1052
     * the documentation on {@link Grpc#newChannelBuilder} for the format of a target string.
1053
     *
1054
     * <p>The target string will be resolved by a {@link NameResolver} created according to the
1055
     * target string.
1056
     *
1057
     * <p>The LoadBalancer is responsible for closing unused OOB channels, and closing all OOB
1058
     * channels within {@link #shutdown}.
1059
     *
1060
     * @since 1.35.0
1061
     */
1062
    public ManagedChannelBuilder<?> createResolvingOobChannelBuilder(
1063
        String target, ChannelCredentials creds) {
1064
      throw new UnsupportedOperationException();
×
1065
    }
1066

1067
    /**
1068
     * Set a new state with a new picker to the channel.
1069
     *
1070
     * <p>When a new picker is provided via {@code updateBalancingState()}, the channel will apply
1071
     * the picker on all buffered RPCs, by calling {@link SubchannelPicker#pickSubchannel(
1072
     * LoadBalancer.PickSubchannelArgs)}.
1073
     *
1074
     * <p>The channel will hold the picker and use it for all RPCs, until {@code
1075
     * updateBalancingState()} is called again and a new picker replaces the old one.  If {@code
1076
     * updateBalancingState()} has never been called, the channel will buffer all RPCs until a
1077
     * picker is provided.
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
     * <p>The passed state will be the channel's new state. The SHUTDOWN state should not be passed
1084
     * and its behavior is undefined.
1085
     *
1086
     * @since 1.6.0
1087
     */
1088
    public abstract void updateBalancingState(
1089
        @Nonnull ConnectivityState newState, @Nonnull SubchannelPicker newPicker);
1090

1091
    /**
1092
     * Call {@link NameResolver#refresh} on the channel's resolver.
1093
     *
1094
     * <p>It should be called from the Synchronization Context.  Currently will log a warning if
1095
     * violated.  It will become an exception eventually.  See <a
1096
     * href="https://github.com/grpc/grpc-java/issues/5015">#5015</a> for the background.
1097
     *
1098
     * @since 1.18.0
1099
     */
1100
    public void refreshNameResolution() {
1101
      throw new UnsupportedOperationException();
×
1102
    }
1103

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

1126
    /**
1127
     * Returns a {@link SynchronizationContext} that runs tasks in the same Synchronization Context
1128
     * as that the callback methods on the {@link LoadBalancer} interface are run in.
1129
     *
1130
     * <p>Pro-tip: in order to call {@link SynchronizationContext#schedule}, you need to provide a
1131
     * {@link ScheduledExecutorService}.  {@link #getScheduledExecutorService} is provided for your
1132
     * convenience.
1133
     *
1134
     * @since 1.17.0
1135
     */
1136
    public SynchronizationContext getSynchronizationContext() {
1137
      // TODO(zhangkun): make getSynchronizationContext() abstract after runSerialized() is deleted
1138
      throw new UnsupportedOperationException();
×
1139
    }
1140

1141
    /**
1142
     * Returns a {@link ScheduledExecutorService} for scheduling delayed tasks.
1143
     *
1144
     * <p>This service is a shared resource and is only meant for quick tasks.  DO NOT block or run
1145
     * time-consuming tasks.
1146
     *
1147
     * <p>The returned service doesn't support {@link ScheduledExecutorService#shutdown shutdown()}
1148
     * and {@link ScheduledExecutorService#shutdownNow shutdownNow()}.  They will throw if called.
1149
     *
1150
     * @since 1.17.0
1151
     */
1152
    public ScheduledExecutorService getScheduledExecutorService() {
1153
      throw new UnsupportedOperationException();
×
1154
    }
1155

1156
    /**
1157
     * Returns the authority string of the channel, which is derived from the DNS-style target name.
1158
     * If overridden by a load balancer, {@link #getUnsafeChannelCredentials} must also be
1159
     * overridden to call {@link #getChannelCredentials} or provide appropriate credentials.
1160
     *
1161
     * @since 1.2.0
1162
     */
1163
    public abstract String getAuthority();
1164

1165
    /**
1166
     * Returns the ChannelCredentials used to construct the channel, without bearer tokens.
1167
     *
1168
     * @since 1.35.0
1169
     */
1170
    public ChannelCredentials getChannelCredentials() {
1171
      return getUnsafeChannelCredentials().withoutBearerTokens();
×
1172
    }
1173

1174
    /**
1175
     * Returns the UNSAFE ChannelCredentials used to construct the channel,
1176
     * including bearer tokens. Load balancers should generally have no use for
1177
     * these credentials and use of them is heavily discouraged. These must be used
1178
     * <em>very</em> carefully to avoid sending bearer tokens to untrusted servers
1179
     * as the server could then impersonate the client. Generally it is only safe
1180
     * to use these credentials when communicating with the backend.
1181
     *
1182
     * @since 1.35.0
1183
     */
1184
    public ChannelCredentials getUnsafeChannelCredentials() {
1185
      throw new UnsupportedOperationException();
×
1186
    }
1187

1188
    /**
1189
     * Returns the {@link ChannelLogger} for the Channel served by this LoadBalancer.
1190
     *
1191
     * @since 1.17.0
1192
     */
1193
    public ChannelLogger getChannelLogger() {
1194
      throw new UnsupportedOperationException();
×
1195
    }
1196

1197
    /**
1198
     * Returns the {@link NameResolver.Args} that the Channel uses to create {@link NameResolver}s.
1199
     *
1200
     * @since 1.22.0
1201
     */
1202
    public NameResolver.Args getNameResolverArgs() {
1203
      throw new UnsupportedOperationException();
×
1204
    }
1205

1206
    /**
1207
     * Returns the {@link NameResolverRegistry} that the Channel uses to look for {@link
1208
     * NameResolver}s.
1209
     *
1210
     * @since 1.22.0
1211
     */
1212
    public NameResolverRegistry getNameResolverRegistry() {
1213
      throw new UnsupportedOperationException();
×
1214
    }
1215

1216
    /**
1217
     * Returns the {@link MetricRecorder} that the channel uses to record metrics.
1218
     *
1219
     * @since 1.64.0
1220
     */
1221
    @ExperimentalApi("https://github.com/grpc/grpc-java/issues/11110")
1222
    public MetricRecorder getMetricRecorder() {
1223
      throw new UnsupportedOperationException();
×
1224
    }
1225
  }
1226

1227
  /**
1228
   * A logical connection to a server, or a group of equivalent servers represented by an {@link 
1229
   * EquivalentAddressGroup}.
1230
   *
1231
   * <p>It maintains at most one physical connection (aka transport) for sending new RPCs, while
1232
   * also keeps track of previous transports that has been shut down but not terminated yet.
1233
   *
1234
   * <p>If there isn't an active transport yet, and an RPC is assigned to the Subchannel, it will
1235
   * create a new transport.  It won't actively create transports otherwise.  {@link
1236
   * #requestConnection requestConnection()} can be used to ask Subchannel to create a transport if
1237
   * there isn't any.
1238
   *
1239
   * <p>{@link #start} must be called prior to calling any other methods, with the exception of
1240
   * {@link #shutdown}, which can be called at any time.
1241
   *
1242
   * @since 1.2.0
1243
   */
1244
  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
1245
  public abstract static class Subchannel {
1✔
1246
    /**
1247
     * Starts the Subchannel.  Can only be called once.
1248
     *
1249
     * <p>Must be called prior to any other method on this class, except for {@link #shutdown} which
1250
     * may be called at any time.
1251
     *
1252
     * <p>Must be called from the {@link Helper#getSynchronizationContext Synchronization Context},
1253
     * otherwise it may throw.  See <a href="https://github.com/grpc/grpc-java/issues/5015">
1254
     * #5015</a> for more discussions.
1255
     *
1256
     * @param listener receives state updates for this Subchannel.
1257
     */
1258
    public void start(SubchannelStateListener listener) {
1259
      throw new UnsupportedOperationException("Not implemented");
×
1260
    }
1261

1262
    /**
1263
     * Shuts down the Subchannel.  After this method is called, this Subchannel should no longer
1264
     * be returned by the latest {@link SubchannelPicker picker}, and can be safely discarded.
1265
     *
1266
     * <p>Calling it on an already shut-down Subchannel has no effect.
1267
     *
1268
     * <p>It should be called from the Synchronization Context.  Currently will log a warning if
1269
     * violated.  It will become an exception eventually.  See <a
1270
     * href="https://github.com/grpc/grpc-java/issues/5015">#5015</a> for the background.
1271
     *
1272
     * @since 1.2.0
1273
     */
1274
    public abstract void shutdown();
1275

1276
    /**
1277
     * Asks the Subchannel to create a connection (aka transport), if there isn't an active one.
1278
     *
1279
     * <p>It should be called from the Synchronization Context.  Currently will log a warning if
1280
     * violated.  It will become an exception eventually.  See <a
1281
     * href="https://github.com/grpc/grpc-java/issues/5015">#5015</a> for the background.
1282
     *
1283
     * @since 1.2.0
1284
     */
1285
    public abstract void requestConnection();
1286

1287
    /**
1288
     * Returns the addresses that this Subchannel is bound to.  This can be called only if
1289
     * the Subchannel has only one {@link EquivalentAddressGroup}.  Under the hood it calls
1290
     * {@link #getAllAddresses}.
1291
     *
1292
     * <p>It should be called from the Synchronization Context.  Currently will log a warning if
1293
     * violated.  It will become an exception eventually.  See <a
1294
     * href="https://github.com/grpc/grpc-java/issues/5015">#5015</a> for the background.
1295
     *
1296
     * @throws IllegalStateException if this subchannel has more than one EquivalentAddressGroup.
1297
     *         Use {@link #getAllAddresses} instead
1298
     * @since 1.2.0
1299
     */
1300
    public final EquivalentAddressGroup getAddresses() {
1301
      List<EquivalentAddressGroup> groups = getAllAddresses();
1✔
1302
      Preconditions.checkState(groups != null && groups.size() == 1,
1✔
1303
          "%s does not have exactly one group", groups);
1304
      return groups.get(0);
1✔
1305
    }
1306

1307
    /**
1308
     * Returns the addresses that this Subchannel is bound to. The returned list will not be empty.
1309
     *
1310
     * <p>It should be called from the Synchronization Context.  Currently will log a warning if
1311
     * violated.  It will become an exception eventually.  See <a
1312
     * href="https://github.com/grpc/grpc-java/issues/5015">#5015</a> for the background.
1313
     *
1314
     * @since 1.14.0
1315
     */
1316
    public List<EquivalentAddressGroup> getAllAddresses() {
1317
      throw new UnsupportedOperationException();
×
1318
    }
1319

1320
    /**
1321
     * The same attributes passed to {@link Helper#createSubchannel Helper.createSubchannel()}.
1322
     * LoadBalancer can use it to attach additional information here, e.g., the shard this
1323
     * Subchannel belongs to.
1324
     *
1325
     * @since 1.2.0
1326
     */
1327
    public abstract Attributes getAttributes();
1328

1329
    /**
1330
     * (Internal use only) returns a {@link Channel} that is backed by this Subchannel.  This allows
1331
     * a LoadBalancer to issue its own RPCs for auxiliary purposes, such as health-checking, on
1332
     * already-established connections.  This channel has certain restrictions:
1333
     * <ol>
1334
     *   <li>It can issue RPCs only if the Subchannel is {@code READY}. If {@link
1335
     *   Channel#newCall} is called when the Subchannel is not {@code READY}, the RPC will fail
1336
     *   immediately.</li>
1337
     *   <li>It doesn't support {@link CallOptions#withWaitForReady wait-for-ready} RPCs. Such RPCs
1338
     *   will fail immediately.</li>
1339
     * </ol>
1340
     *
1341
     * <p>RPCs made on this Channel is not counted when determining ManagedChannel's {@link
1342
     * ManagedChannelBuilder#idleTimeout idle mode}.  In other words, they won't prevent
1343
     * ManagedChannel from entering idle mode.
1344
     *
1345
     * <p>Warning: RPCs made on this channel will prevent a shut-down transport from terminating. If
1346
     * you make long-running RPCs, you need to make sure they will finish in time after the
1347
     * Subchannel has transitioned away from {@code READY} state
1348
     * (notified through {@link #handleSubchannelState}).
1349
     *
1350
     * <p>Warning: this is INTERNAL API, is not supposed to be used by external users, and may
1351
     * change without notice. If you think you must use it, please file an issue.
1352
     */
1353
    @Internal
1354
    public Channel asChannel() {
1355
      throw new UnsupportedOperationException();
×
1356
    }
1357

1358
    /**
1359
     * Returns a {@link ChannelLogger} for this Subchannel.
1360
     *
1361
     * @since 1.17.0
1362
     */
1363
    public ChannelLogger getChannelLogger() {
1364
      throw new UnsupportedOperationException();
×
1365
    }
1366

1367
    /**
1368
     * Replaces the existing addresses used with this {@code Subchannel}. If the new and old
1369
     * addresses overlap, the Subchannel can continue using an existing connection.
1370
     *
1371
     * <p>It must be called from the Synchronization Context or will throw.
1372
     *
1373
     * @throws IllegalArgumentException if {@code addrs} is empty
1374
     * @since 1.22.0
1375
     */
1376
    public void updateAddresses(List<EquivalentAddressGroup> addrs) {
1377
      throw new UnsupportedOperationException();
×
1378
    }
1379

1380
    /**
1381
     * (Internal use only) returns an object that represents the underlying subchannel that is used
1382
     * by the Channel for sending RPCs when this {@link Subchannel} is picked.  This is an opaque
1383
     * object that is both provided and consumed by the Channel.  Its type <strong>is not</strong>
1384
     * {@code Subchannel}.
1385
     *
1386
     * <p>Warning: this is INTERNAL API, is not supposed to be used by external users, and may
1387
     * change without notice. If you think you must use it, please file an issue and we can consider
1388
     * removing its "internal" status.
1389
     */
1390
    @Internal
1391
    public Object getInternalSubchannel() {
1392
      throw new UnsupportedOperationException();
×
1393
    }
1394
  }
1395

1396
  /**
1397
   * Receives state changes for one {@link Subchannel}. All methods are run under {@link
1398
   * Helper#getSynchronizationContext}.
1399
   *
1400
   * @since 1.22.0
1401
   */
1402
  public interface SubchannelStateListener {
1403
    /**
1404
     * Handles a state change on a Subchannel.
1405
     *
1406
     * <p>The initial state of a Subchannel is IDLE. You won't get a notification for the initial
1407
     * IDLE state.
1408
     *
1409
     * <p>If the new state is not SHUTDOWN, this method should create a new picker and call {@link
1410
     * Helper#updateBalancingState Helper.updateBalancingState()}.  Failing to do so may result in
1411
     * unnecessary delays of RPCs. Please refer to {@link PickResult#withSubchannel
1412
     * PickResult.withSubchannel()}'s javadoc for more information.
1413
     *
1414
     * <p>When a subchannel's state is IDLE or TRANSIENT_FAILURE and the address for the subchannel
1415
     * was received in {@link LoadBalancer#handleResolvedAddresses}, load balancers should call
1416
     * {@link Helper#refreshNameResolution} to inform polling name resolvers that it is an
1417
     * appropriate time to refresh the addresses. Without the refresh, changes to the addresses may
1418
     * never be detected.
1419
     *
1420
     * <p>SHUTDOWN can only happen in two cases.  One is that LoadBalancer called {@link
1421
     * Subchannel#shutdown} earlier, thus it should have already discarded this Subchannel.  The
1422
     * other is that Channel is doing a {@link ManagedChannel#shutdownNow forced shutdown} or has
1423
     * already terminated, thus there won't be further requests to LoadBalancer.  Therefore, the
1424
     * LoadBalancer usually don't need to react to a SHUTDOWN state.
1425
     *
1426
     * @param newState the new state
1427
     * @since 1.22.0
1428
     */
1429
    void onSubchannelState(ConnectivityStateInfo newState);
1430
  }
1431

1432
  /**
1433
   * Factory to create {@link LoadBalancer} instance.
1434
   *
1435
   * @since 1.2.0
1436
   */
1437
  @ThreadSafe
1438
  @ExperimentalApi("https://github.com/grpc/grpc-java/issues/1771")
1439
  public abstract static class Factory {
1✔
1440
    /**
1441
     * Creates a {@link LoadBalancer} that will be used inside a channel.
1442
     *
1443
     * @since 1.2.0
1444
     */
1445
    public abstract LoadBalancer newLoadBalancer(Helper helper);
1446
  }
1447

1448
  /**
1449
   * A picker that always returns an erring pick.
1450
   *
1451
   * @deprecated Use {@code new FixedResultPicker(PickResult.withError(error))} instead.
1452
   */
1453
  @Deprecated
1454
  public static final class ErrorPicker extends SubchannelPicker {
1455

1456
    private final Status error;
1457

1458
    public ErrorPicker(Status error) {
×
1459
      this.error = checkNotNull(error, "error");
×
1460
    }
×
1461

1462
    @Override
1463
    public PickResult pickSubchannel(PickSubchannelArgs args) {
1464
      return PickResult.withError(error);
×
1465
    }
1466

1467
    @Override
1468
    public String toString() {
1469
      return MoreObjects.toStringHelper(this)
×
1470
          .add("error", error)
×
1471
          .toString();
×
1472
    }
1473
  }
1474

1475
  /** A picker that always returns the same result. */
1476
  public static final class FixedResultPicker extends SubchannelPicker {
1477
    private final PickResult result;
1478

1479
    public FixedResultPicker(PickResult result) {
1✔
1480
      this.result = Preconditions.checkNotNull(result, "result");
1✔
1481
    }
1✔
1482

1483
    @Override
1484
    public PickResult pickSubchannel(PickSubchannelArgs args) {
1485
      return result;
1✔
1486
    }
1487

1488
    @Override
1489
    public String toString() {
1490
      return "FixedResultPicker(" + result + ")";
1✔
1491
    }
1492
  }
1493
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc