Skip to content

Commit 67fc2e1

Browse files
authored
Add new classes for eliminating xds config tears (grpc#11740)
* Framework definition to support A74
1 parent 90b1c4f commit 67fc2e1

File tree

10 files changed

+2186
-25
lines changed

10 files changed

+2186
-25
lines changed

xds/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ dependencies {
4646
thirdpartyImplementation project(':grpc-protobuf'),
4747
project(':grpc-stub')
4848
compileOnly sourceSets.thirdparty.output
49+
testCompileOnly sourceSets.thirdparty.output
4950
implementation project(':grpc-stub'),
5051
project(':grpc-core'),
5152
project(':grpc-util'),
@@ -59,6 +60,7 @@ dependencies {
5960
libraries.protobuf.java.util
6061
def nettyDependency = implementation project(':grpc-netty')
6162

63+
testImplementation project(':grpc-api')
6264
testImplementation project(':grpc-rls')
6365
testImplementation project(':grpc-inprocess')
6466
testImplementation testFixtures(project(':grpc-core')),
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
/*
2+
* Copyright 2024 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.xds;
18+
19+
import static com.google.common.base.Preconditions.checkNotNull;
20+
21+
import com.google.common.collect.ImmutableMap;
22+
import io.grpc.StatusOr;
23+
import io.grpc.xds.XdsClusterResource.CdsUpdate;
24+
import io.grpc.xds.XdsEndpointResource.EdsUpdate;
25+
import io.grpc.xds.XdsListenerResource.LdsUpdate;
26+
import io.grpc.xds.XdsRouteConfigureResource.RdsUpdate;
27+
import java.io.Closeable;
28+
import java.util.HashMap;
29+
import java.util.Map;
30+
import java.util.Objects;
31+
32+
/**
33+
* Represents the xDS configuration tree for a specified Listener.
34+
*/
35+
final class XdsConfig {
36+
private final LdsUpdate listener;
37+
private final RdsUpdate route;
38+
private final VirtualHost virtualHost;
39+
private final ImmutableMap<String, StatusOr<XdsClusterConfig>> clusters;
40+
private final int hashCode;
41+
42+
XdsConfig(LdsUpdate listener, RdsUpdate route, Map<String, StatusOr<XdsClusterConfig>> clusters,
43+
VirtualHost virtualHost) {
44+
this(listener, route, virtualHost, ImmutableMap.copyOf(clusters));
45+
}
46+
47+
public XdsConfig(LdsUpdate listener, RdsUpdate route, VirtualHost virtualHost,
48+
ImmutableMap<String, StatusOr<XdsClusterConfig>> clusters) {
49+
this.listener = listener;
50+
this.route = route;
51+
this.virtualHost = virtualHost;
52+
this.clusters = clusters;
53+
54+
hashCode = Objects.hash(listener, route, virtualHost, clusters);
55+
}
56+
57+
@Override
58+
public boolean equals(Object obj) {
59+
if (!(obj instanceof XdsConfig)) {
60+
return false;
61+
}
62+
63+
XdsConfig o = (XdsConfig) obj;
64+
65+
return hashCode() == o.hashCode() && Objects.equals(listener, o.listener)
66+
&& Objects.equals(route, o.route) && Objects.equals(virtualHost, o.virtualHost)
67+
&& Objects.equals(clusters, o.clusters);
68+
}
69+
70+
@Override
71+
public int hashCode() {
72+
return hashCode;
73+
}
74+
75+
@Override
76+
public String toString() {
77+
StringBuilder builder = new StringBuilder();
78+
builder.append("XdsConfig{")
79+
.append("\n listener=").append(listener)
80+
.append(",\n route=").append(route)
81+
.append(",\n virtualHost=").append(virtualHost)
82+
.append(",\n clusters=").append(clusters)
83+
.append("\n}");
84+
return builder.toString();
85+
}
86+
87+
public LdsUpdate getListener() {
88+
return listener;
89+
}
90+
91+
public RdsUpdate getRoute() {
92+
return route;
93+
}
94+
95+
public VirtualHost getVirtualHost() {
96+
return virtualHost;
97+
}
98+
99+
public ImmutableMap<String, StatusOr<XdsClusterConfig>> getClusters() {
100+
return clusters;
101+
}
102+
103+
static final class XdsClusterConfig {
104+
private final String clusterName;
105+
private final CdsUpdate clusterResource;
106+
private final StatusOr<EdsUpdate> endpoint; //Will be null for non-EDS clusters
107+
108+
XdsClusterConfig(String clusterName, CdsUpdate clusterResource,
109+
StatusOr<EdsUpdate> endpoint) {
110+
this.clusterName = checkNotNull(clusterName, "clusterName");
111+
this.clusterResource = checkNotNull(clusterResource, "clusterResource");
112+
this.endpoint = endpoint;
113+
}
114+
115+
@Override
116+
public int hashCode() {
117+
int endpointHash = (endpoint != null) ? endpoint.hashCode() : 0;
118+
return clusterName.hashCode() + clusterResource.hashCode() + endpointHash;
119+
}
120+
121+
@Override
122+
public boolean equals(Object obj) {
123+
if (!(obj instanceof XdsClusterConfig)) {
124+
return false;
125+
}
126+
XdsClusterConfig o = (XdsClusterConfig) obj;
127+
return Objects.equals(clusterName, o.clusterName)
128+
&& Objects.equals(clusterResource, o.clusterResource)
129+
&& Objects.equals(endpoint, o.endpoint);
130+
}
131+
132+
@Override
133+
public String toString() {
134+
StringBuilder builder = new StringBuilder();
135+
builder.append("XdsClusterConfig{clusterName=").append(clusterName)
136+
.append(", clusterResource=").append(clusterResource)
137+
.append(", endpoint=").append(endpoint).append("}");
138+
return builder.toString();
139+
}
140+
141+
public String getClusterName() {
142+
return clusterName;
143+
}
144+
145+
public CdsUpdate getClusterResource() {
146+
return clusterResource;
147+
}
148+
149+
public StatusOr<EdsUpdate> getEndpoint() {
150+
return endpoint;
151+
}
152+
}
153+
154+
static final class XdsConfigBuilder {
155+
private LdsUpdate listener;
156+
private RdsUpdate route;
157+
private Map<String, StatusOr<XdsClusterConfig>> clusters = new HashMap<>();
158+
private VirtualHost virtualHost;
159+
160+
XdsConfigBuilder setListener(LdsUpdate listener) {
161+
this.listener = checkNotNull(listener, "listener");
162+
return this;
163+
}
164+
165+
XdsConfigBuilder setRoute(RdsUpdate route) {
166+
this.route = checkNotNull(route, "route");
167+
return this;
168+
}
169+
170+
XdsConfigBuilder addCluster(String name, StatusOr<XdsClusterConfig> clusterConfig) {
171+
checkNotNull(name, "name");
172+
checkNotNull(clusterConfig, "clusterConfig");
173+
clusters.put(name, clusterConfig);
174+
return this;
175+
}
176+
177+
XdsConfigBuilder setVirtualHost(VirtualHost virtualHost) {
178+
this.virtualHost = checkNotNull(virtualHost, "virtualHost");
179+
return this;
180+
}
181+
182+
XdsConfig build() {
183+
checkNotNull(listener, "listener");
184+
checkNotNull(route, "route");
185+
return new XdsConfig(listener, route, clusters, virtualHost);
186+
}
187+
}
188+
189+
public interface XdsClusterSubscriptionRegistry {
190+
Closeable subscribeToCluster(String clusterName);
191+
}
192+
}

0 commit comments

Comments
 (0)