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

grpc / grpc-java / #20297

01 Jun 2026 04:04AM UTC coverage: 88.886% (-0.002%) from 88.888%
#20297

push

github

web-flow
xds: Hold parsed service config in CdsUpdate

This avoids re-parsing the config within CdsLB, as the providers could
have changed and the config may no longer be valid.

Many usages of ServiceConfigUtil.unwrapLoadBalancingConfig() were
replaced with public API, which should be less brittle to internal
changes. Similarly, config.equals() was added for LBs least_request,
ring_hash, wrr to use more public APIs in testing. But I've gone out of
my way to avoid using equals for XdsClient change detection, by
preserving the original "JSON" config.

This fixes a bug in WRR config parsing which prevented it from parsing
errorUtilizationPenalty as it assumed it would be a Float, not a Double
like our parser actually generates and our API requires.
JsonUtil.getNumberAsFloat() was added specifically for WRR and has never
worked as JSON Numbers will always be Doubles.

In XdsClusterResource.CdsUpdate, the LB-specific fields like minRingSize
were already not used at all, so this commit deletes them as it seems a
relevant cleanup.

Fixes #12733

36493 of 41056 relevant lines covered (88.89%)

0.89 hits per line

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

87.88
/../netty/src/main/java/io/grpc/netty/ClientTransportLifecycleManager.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.netty;
18

19
import com.google.errorprone.annotations.CanIgnoreReturnValue;
20
import io.grpc.Attributes;
21
import io.grpc.Status;
22
import io.grpc.internal.DisconnectError;
23
import io.grpc.internal.ManagedClientTransport;
24

25
/** Maintainer of transport lifecycle status. */
26
final class ClientTransportLifecycleManager {
27
  private final ManagedClientTransport.Listener listener;
28
  private boolean transportReady;
29
  private boolean transportShutdown;
30
  private boolean transportInUse;
31
  /** null iff !transportShutdown. */
32
  private Status shutdownStatus;
33
  /** null iff !transportShutdown. */
34
  private boolean transportTerminated;
35

36
  public ClientTransportLifecycleManager(ManagedClientTransport.Listener listener) {
1✔
37
    this.listener = listener;
1✔
38
  }
1✔
39

40
  public Attributes filterAttributes(Attributes attributes) {
41
    if (transportReady || transportShutdown) {
1✔
42
      return attributes;
×
43
    }
44
    return listener.filterTransport(attributes);
1✔
45
  }
46

47
  public void notifyReady() {
48
    if (transportReady || transportShutdown) {
1✔
49
      return;
×
50
    }
51
    transportReady = true;
1✔
52
    listener.transportReady();
1✔
53
  }
1✔
54

55
  /**
56
   * Marks transport as shutdown, but does not set the error status. This must eventually be
57
   * followed by a call to notifyShutdown.
58
   */
59
  public void notifyGracefulShutdown(Status s, DisconnectError disconnectError) {
60
    if (transportShutdown) {
1✔
61
      return;
1✔
62
    }
63
    transportShutdown = true;
1✔
64
    listener.transportShutdown(s, disconnectError);
1✔
65
  }
1✔
66

67
  /** Returns {@code true} if was the first shutdown. */
68
  @CanIgnoreReturnValue
69
  public boolean notifyShutdown(Status s, DisconnectError disconnectError) {
70
    notifyGracefulShutdown(s, disconnectError);
1✔
71
    if (shutdownStatus != null) {
1✔
72
      return false;
1✔
73
    }
74
    shutdownStatus = s;
1✔
75
    return true;
1✔
76
  }
77

78
  public void notifyInUse(boolean inUse) {
79
    if (inUse == transportInUse) {
1✔
80
      return;
×
81
    }
82
    transportInUse = inUse;
1✔
83
    listener.transportInUse(inUse);
1✔
84
  }
1✔
85

86
  public void notifyTerminated(Status s, DisconnectError disconnectError) {
87
    if (transportTerminated) {
1✔
88
      return;
×
89
    }
90
    transportTerminated = true;
1✔
91
    notifyShutdown(s, disconnectError);
1✔
92
    listener.transportTerminated();
1✔
93
  }
1✔
94

95
  public Status getShutdownStatus() {
96
    return shutdownStatus;
1✔
97
  }
98

99
}
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