15
15
*
16
16
*/
17
17
18
- import { connectivityState , status , Metadata , logVerbosity , experimental } from '@grpc/grpc-js' ;
18
+ import { connectivityState , status , Metadata , logVerbosity , experimental , LoadBalancingConfig } from '@grpc/grpc-js' ;
19
19
import { getSingletonXdsClient , Watcher , XdsClient } from './xds-client' ;
20
20
import { Cluster__Output } from './generated/envoy/config/cluster/v3/Cluster' ;
21
21
import SubchannelAddress = experimental . SubchannelAddress ;
@@ -24,17 +24,18 @@ import ChildLoadBalancerHandler = experimental.ChildLoadBalancerHandler;
24
24
import LoadBalancer = experimental . LoadBalancer ;
25
25
import ChannelControlHelper = experimental . ChannelControlHelper ;
26
26
import registerLoadBalancerType = experimental . registerLoadBalancerType ;
27
- import LoadBalancingConfig = experimental . LoadBalancingConfig ;
28
- import OutlierDetectionLoadBalancingConfig = experimental . OutlierDetectionLoadBalancingConfig ;
27
+ import TypedLoadBalancingConfig = experimental . TypedLoadBalancingConfig ;
29
28
import SuccessRateEjectionConfig = experimental . SuccessRateEjectionConfig ;
30
29
import FailurePercentageEjectionConfig = experimental . FailurePercentageEjectionConfig ;
31
30
import QueuePicker = experimental . QueuePicker ;
31
+ import OutlierDetectionRawConfig = experimental . OutlierDetectionRawConfig ;
32
+ import parseLoadBalancingConfig = experimental . parseLoadBalancingConfig ;
32
33
import { OutlierDetection__Output } from './generated/envoy/config/cluster/v3/OutlierDetection' ;
33
34
import { Duration__Output } from './generated/google/protobuf/Duration' ;
34
35
import { EXPERIMENTAL_OUTLIER_DETECTION } from './environment' ;
35
- import { DiscoveryMechanism , XdsClusterResolverChildPolicyHandler , XdsClusterResolverLoadBalancingConfig } from './load-balancer-xds-cluster-resolver' ;
36
+ import { DiscoveryMechanism , XdsClusterResolverChildPolicyHandler } from './load-balancer-xds-cluster-resolver' ;
36
37
import { CLUSTER_CONFIG_TYPE_URL , decodeSingleResource } from './resources' ;
37
- import { CdsUpdate , ClusterResourceType , OutlierDetectionUpdate } from './xds-resource-type/cluster-resource-type' ;
38
+ import { CdsUpdate , ClusterResourceType } from './xds-resource-type/cluster-resource-type' ;
38
39
39
40
const TRACER_NAME = 'cds_balancer' ;
40
41
@@ -44,7 +45,7 @@ function trace(text: string): void {
44
45
45
46
const TYPE_NAME = 'cds' ;
46
47
47
- export class CdsLoadBalancingConfig implements LoadBalancingConfig {
48
+ class CdsLoadBalancingConfig implements TypedLoadBalancingConfig {
48
49
getLoadBalancerName ( ) : string {
49
50
return TYPE_NAME ;
50
51
}
@@ -72,29 +73,6 @@ export class CdsLoadBalancingConfig implements LoadBalancingConfig {
72
73
}
73
74
}
74
75
75
- function durationToMs ( duration : Duration__Output ) : number {
76
- return ( Number ( duration . seconds ) * 1_000 + duration . nanos / 1_000_000 ) | 0 ;
77
- }
78
-
79
- function translateOutlierDetectionConfig ( outlierDetection : OutlierDetectionUpdate | undefined ) : OutlierDetectionLoadBalancingConfig | undefined {
80
- if ( ! EXPERIMENTAL_OUTLIER_DETECTION ) {
81
- return undefined ;
82
- }
83
- if ( ! outlierDetection ) {
84
- /* No-op outlier detection config, with all fields unset. */
85
- return new OutlierDetectionLoadBalancingConfig ( null , null , null , null , null , null , [ ] ) ;
86
- }
87
- return new OutlierDetectionLoadBalancingConfig (
88
- outlierDetection . intervalMs ,
89
- outlierDetection . baseEjectionTimeMs ,
90
- outlierDetection . maxEjectionTimeMs ,
91
- outlierDetection . maxEjectionPercent ,
92
- outlierDetection . successRateConfig ,
93
- outlierDetection . failurePercentageConfig ,
94
- [ ]
95
- ) ;
96
- }
97
-
98
76
interface ClusterEntry {
99
77
watcher : Watcher < CdsUpdate > ;
100
78
latestUpdate ?: CdsUpdate ;
@@ -133,16 +111,16 @@ function generateDiscoverymechanismForCdsUpdate(config: CdsUpdate): DiscoveryMec
133
111
type : config . type ,
134
112
eds_service_name : config . edsServiceName ,
135
113
dns_hostname : config . dnsHostname ,
136
- outlier_detection : translateOutlierDetectionConfig ( config . outlierDetectionUpdate )
114
+ outlier_detection : config . outlierDetectionUpdate
137
115
} ;
138
116
}
139
117
140
118
const RECURSION_DEPTH_LIMIT = 15 ;
141
119
142
120
/**
143
121
* Prerequisite: isClusterTreeFullyUpdated(tree, root)
144
- * @param tree
145
- * @param root
122
+ * @param tree
123
+ * @param root
146
124
*/
147
125
function getDiscoveryMechanismList ( tree : ClusterTree , root : string ) : DiscoveryMechanism [ ] {
148
126
const visited = new Set < string > ( ) ;
@@ -189,6 +167,11 @@ export class CdsLoadBalancer implements LoadBalancer {
189
167
this . childBalancer = new XdsClusterResolverChildPolicyHandler ( channelControlHelper ) ;
190
168
}
191
169
170
+ private reportError ( errorMessage : string ) {
171
+ trace ( 'CDS cluster reporting error ' + errorMessage ) ;
172
+ this . channelControlHelper . updateState ( connectivityState . TRANSIENT_FAILURE , new UnavailablePicker ( { code : status . UNAVAILABLE , details : errorMessage , metadata : new Metadata ( ) } ) ) ;
173
+ }
174
+
192
175
private addCluster ( cluster : string ) {
193
176
if ( cluster in this . clusterTree ) {
194
177
return ;
@@ -208,19 +191,28 @@ export class CdsLoadBalancer implements LoadBalancer {
208
191
try {
209
192
discoveryMechanismList = getDiscoveryMechanismList ( this . clusterTree , this . latestConfig ! . getCluster ( ) ) ;
210
193
} catch ( e ) {
211
- this . channelControlHelper . updateState ( connectivityState . TRANSIENT_FAILURE , new UnavailablePicker ( { code : status . UNAVAILABLE , details : e . message , metadata : new Metadata ( ) } ) ) ;
194
+ this . reportError ( ( e as Error ) . message ) ;
195
+ return ;
196
+ }
197
+ const clusterResolverConfig : LoadBalancingConfig = {
198
+ xds_cluster_resolver : {
199
+ discovery_mechanisms : discoveryMechanismList ,
200
+ locality_picking_policy : [ ] ,
201
+ endpoint_picking_policy : [ ]
202
+ }
203
+ } ;
204
+ let parsedClusterResolverConfig : TypedLoadBalancingConfig ;
205
+ try {
206
+ parsedClusterResolverConfig = parseLoadBalancingConfig ( clusterResolverConfig ) ;
207
+ } catch ( e ) {
208
+ this . reportError ( `CDS cluster ${ this . latestConfig ?. getCluster ( ) } child config parsing failed with error ${ ( e as Error ) . message } ` ) ;
212
209
return ;
213
210
}
214
- const clusterResolverConfig = new XdsClusterResolverLoadBalancingConfig (
215
- discoveryMechanismList ,
216
- [ ] ,
217
- [ ]
218
- ) ;
219
211
trace ( 'Child update config: ' + JSON . stringify ( clusterResolverConfig ) ) ;
220
212
this . updatedChild = true ;
221
213
this . childBalancer . updateAddressList (
222
214
[ ] ,
223
- clusterResolverConfig ,
215
+ parsedClusterResolverConfig ,
224
216
this . latestAttributes
225
217
) ;
226
218
}
@@ -231,20 +223,13 @@ export class CdsLoadBalancer implements LoadBalancer {
231
223
this . clusterTree [ cluster ] . latestUpdate = undefined ;
232
224
this . clusterTree [ cluster ] . children = [ ] ;
233
225
}
234
- this . channelControlHelper . updateState ( connectivityState . TRANSIENT_FAILURE , new UnavailablePicker ( { code : status . UNAVAILABLE , details : `CDS resource ${ cluster } does not exist` , metadata : new Metadata ( ) } ) ) ;
226
+ this . reportError ( `CDS resource ${ cluster } does not exist` ) ;
235
227
this . childBalancer . destroy ( ) ;
236
228
} ,
237
229
onError : ( statusObj ) => {
238
230
if ( ! this . updatedChild ) {
239
231
trace ( 'Transitioning to transient failure due to onError update for cluster' + cluster ) ;
240
- this . channelControlHelper . updateState (
241
- connectivityState . TRANSIENT_FAILURE ,
242
- new UnavailablePicker ( {
243
- code : status . UNAVAILABLE ,
244
- details : `xDS request failed with error ${ statusObj . details } ` ,
245
- metadata : new Metadata ( ) ,
246
- } )
247
- ) ;
232
+ this . reportError ( `xDS request failed with error ${ statusObj . details } ` ) ;
248
233
}
249
234
}
250
235
} ) ;
@@ -275,7 +260,7 @@ export class CdsLoadBalancer implements LoadBalancer {
275
260
276
261
updateAddressList (
277
262
addressList : SubchannelAddress [ ] ,
278
- lbConfig : LoadBalancingConfig ,
263
+ lbConfig : TypedLoadBalancingConfig ,
279
264
attributes : { [ key : string ] : unknown }
280
265
) : void {
281
266
if ( ! ( lbConfig instanceof CdsLoadBalancingConfig ) ) {
0 commit comments