Skip to content

Commit 8aec160

Browse files
authored
Merge pull request #1924 from murgatroid99/v1.4.x_upmerge_1
Merge 1.4.x branch into master
2 parents 3e5d102 + 134171c commit 8aec160

File tree

9 files changed

+61
-39
lines changed

9 files changed

+61
-39
lines changed

packages/grpc-js-xds/interop/xds-interop-client.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,13 @@ class CallStatsTracker {
130130

131131
private subscribers: CallSubscriber[] = [];
132132

133+
private removeSubscriber(subscriber: CallSubscriber) {
134+
const index = this.subscribers.indexOf(subscriber);
135+
if (index >= 0) {
136+
this.subscribers.splice(index, 1);
137+
}
138+
}
139+
133140
getCallStats(callCount: number, timeoutSec: number): Promise<LoadBalancerStatsResponse> {
134141
return new Promise((resolve, reject) => {
135142
let finished = false;
@@ -142,7 +149,7 @@ class CallStatsTracker {
142149
setTimeout(() => {
143150
if (!finished) {
144151
finished = true;
145-
this.subscribers.splice(this.subscribers.indexOf(subscriber), 1);
152+
this.removeSubscriber(subscriber);
146153
resolve(subscriber.getFinalStats());
147154
}
148155
}, timeoutSec * 1000)
@@ -155,7 +162,7 @@ class CallStatsTracker {
155162
for (const subscriber of callSubscribers) {
156163
subscriber.addCallStarted();
157164
if (!subscriber.needsMoreCalls()) {
158-
this.subscribers.splice(this.subscribers.indexOf(subscriber), 1);
165+
this.removeSubscriber(subscriber);
159166
}
160167
}
161168
return {

packages/grpc-js-xds/scripts/xds.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ GRPC_NODE_TRACE=xds_client,xds_resolver,cds_balancer,eds_balancer,priority,weigh
5959
--gcp_suffix=$(date '+%s') \
6060
--verbose \
6161
${XDS_V3_OPT-} \
62-
--client_cmd="$(which node) grpc-node/packages/grpc-js-xds/build/interop/xds-interop-client \
62+
--client_cmd="$(which node) --enable-source-maps grpc-node/packages/grpc-js-xds/build/interop/xds-interop-client \
6363
--server=xds:///{server_uri} \
6464
--stats_port={stats_port} \
6565
--qps={qps} \

packages/grpc-js-xds/src/xds-bootstrap.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ function validateXdsServerConfig(obj: any): XdsServerConfig {
109109
return {
110110
serverUri: obj.server_uri,
111111
channelCreds: obj.channel_creds.map(validateChannelCredsConfig),
112-
serverFeatures: obj.server_features
112+
serverFeatures: obj.server_features ?? []
113113
};
114114
}
115115

packages/grpc-js-xds/src/xds-client.ts

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,16 @@ export class XdsClient {
341341
return;
342342
}
343343
trace('Loaded bootstrap info: ' + JSON.stringify(bootstrapInfo, undefined, 2));
344+
if (bootstrapInfo.xdsServers.length < 1) {
345+
trace('Failed to initialize xDS Client. No servers provided in bootstrap info.');
346+
// Bubble this error up to any listeners
347+
this.reportStreamError({
348+
code: status.INTERNAL,
349+
details: 'Failed to initialize xDS Client. No servers provided in bootstrap info.',
350+
metadata: new Metadata(),
351+
});
352+
return;
353+
}
344354
if (bootstrapInfo.xdsServers[0].serverFeatures.indexOf('xds_v3') >= 0) {
345355
this.apiVersion = XdsApiVersion.V3;
346356
} else {
@@ -425,8 +435,7 @@ export class XdsClient {
425435
{channelOverride: channel}
426436
);
427437
this.maybeStartLrsStream();
428-
},
429-
(error) => {
438+
}).catch((error) => {
430439
trace('Failed to initialize xDS Client. ' + error.message);
431440
// Bubble this error up to any listeners
432441
this.reportStreamError({
@@ -507,13 +516,15 @@ export class XdsClient {
507516
}
508517
}
509518

510-
private handleAdsCallError(error: ServiceError) {
519+
private handleAdsCallStatus(streamStatus: StatusObject) {
511520
trace(
512-
'ADS stream ended. code=' + error.code + ' details= ' + error.details
521+
'ADS stream ended. code=' + streamStatus.code + ' details= ' + streamStatus.details
513522
);
514523
this.adsCallV2 = null;
515524
this.adsCallV3 = null;
516-
this.reportStreamError(error);
525+
if (streamStatus.code !== status.OK) {
526+
this.reportStreamError(streamStatus);
527+
}
517528
/* If the backoff timer is no longer running, we do not need to wait any
518529
* more to start the new call. */
519530
if (!this.adsBackoff.isRunning()) {
@@ -535,9 +546,10 @@ export class XdsClient {
535546
this.adsCallV2.on('data', (message: DiscoveryResponse__Output) => {
536547
this.handleAdsResponse(message);
537548
});
538-
this.adsCallV2.on('error', (error: ServiceError) => {
539-
this.handleAdsCallError(error);
549+
this.adsCallV2.on('status', (status: StatusObject) => {
550+
this.handleAdsCallStatus(status);
540551
});
552+
this.adsCallV2.on('error', () => {});
541553
return true;
542554
}
543555

@@ -555,9 +567,10 @@ export class XdsClient {
555567
this.adsCallV3.on('data', (message: DiscoveryResponse__Output) => {
556568
this.handleAdsResponse(message);
557569
});
558-
this.adsCallV3.on('error', (error: ServiceError) => {
559-
this.handleAdsCallError(error);
570+
this.adsCallV3.on('status', (status: StatusObject) => {
571+
this.handleAdsCallStatus(status);
560572
});
573+
this.adsCallV3.on('error', () => {});
561574
return true;
562575
}
563576

@@ -763,9 +776,9 @@ export class XdsClient {
763776
this.receivedLrsSettingsForCurrentStream = true;
764777
}
765778

766-
private handleLrsCallError(error: ServiceError) {
779+
private handleLrsCallStatus(streamStatus: StatusObject) {
767780
trace(
768-
'LRS stream ended. code=' + error.code + ' details= ' + error.details
781+
'LRS stream ended. code=' + streamStatus.code + ' details= ' + streamStatus.details
769782
);
770783
this.lrsCallV2 = null;
771784
this.lrsCallV3 = null;
@@ -789,9 +802,10 @@ export class XdsClient {
789802
this.lrsCallV2.on('data', (message: LoadStatsResponse__Output) => {
790803
this.handleLrsResponse(message);
791804
});
792-
this.lrsCallV2.on('error', (error: ServiceError) => {
793-
this.handleLrsCallError(error);
805+
this.lrsCallV2.on('status', (status: StatusObject) => {
806+
this.handleLrsCallStatus(status);
794807
});
808+
this.lrsCallV2.on('error', () => {});
795809
return true;
796810
}
797811

@@ -807,9 +821,10 @@ export class XdsClient {
807821
this.lrsCallV3.on('data', (message: LoadStatsResponse__Output) => {
808822
this.handleLrsResponse(message);
809823
});
810-
this.lrsCallV3.on('error', (error: ServiceError) => {
811-
this.handleLrsCallError(error);
824+
this.lrsCallV3.on('status', (status: StatusObject) => {
825+
this.handleLrsCallStatus(status);
812826
});
827+
this.lrsCallV3.on('error', () => {});
813828
return true;
814829
}
815830

packages/grpc-js-xds/src/xds-stream-state/eds-state.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,6 @@ export class EdsState implements XdsStreamState<ClusterLoadAssignment__Output> {
163163
}
164164
}
165165
trace('Received EDS updates for cluster names ' + Array.from(allClusterNames));
166-
this.handleMissingNames(allClusterNames);
167166
return null;
168167
}
169168

packages/grpc-js-xds/src/xds-stream-state/lds-state.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,15 +163,21 @@ export class LdsState implements XdsStreamState<Listener__Output> {
163163
this.latestResponses = responses;
164164
this.latestIsV2 = isV2;
165165
const allTargetNames = new Set<string>();
166+
const allRouteConfigNames = new Set<string>();
166167
for (const message of responses) {
167168
allTargetNames.add(message.name);
169+
const httpConnectionManager = decodeSingleResource(HTTP_CONNECTION_MANGER_TYPE_URL_V3, message.api_listener!.api_listener!.value);
170+
if (httpConnectionManager.rds) {
171+
allRouteConfigNames.add(httpConnectionManager.rds.route_config_name);
172+
}
168173
const watchers = this.watchers.get(message.name) ?? [];
169174
for (const watcher of watchers) {
170175
watcher.onValidUpdate(message, isV2);
171176
}
172177
}
173178
trace('Received RDS response with route config names ' + Array.from(allTargetNames));
174179
this.handleMissingNames(allTargetNames);
180+
this.rdsState.handleMissingNames(allRouteConfigNames);
175181
return null;
176182
}
177183

packages/grpc-js-xds/src/xds-stream-state/rds-state.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ export class RdsState implements XdsStreamState<RouteConfiguration__Output> {
172172
return true;
173173
}
174174

175-
private handleMissingNames(allRouteConfigNames: Set<string>) {
175+
handleMissingNames(allRouteConfigNames: Set<string>) {
176176
for (const [routeConfigName, watcherList] of this.watchers.entries()) {
177177
if (!allRouteConfigNames.has(routeConfigName)) {
178178
for (const watcher of watcherList) {
@@ -200,7 +200,6 @@ export class RdsState implements XdsStreamState<RouteConfiguration__Output> {
200200
}
201201
}
202202
trace('Received RDS response with route config names ' + Array.from(allRouteConfigNames));
203-
this.handleMissingNames(allRouteConfigNames);
204203
return null;
205204
}
206205

packages/grpc-js/src/channel.ts

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -192,18 +192,8 @@ export class ChannelImplementation implements Channel {
192192
);
193193
}
194194
if (options) {
195-
if (
196-
typeof options !== 'object' ||
197-
!Object.values(options).every(
198-
(value) =>
199-
typeof value === 'string' ||
200-
typeof value === 'number' ||
201-
typeof value === 'undefined'
202-
)
203-
) {
204-
throw new TypeError(
205-
'Channel options must be an object with string or number values'
206-
);
195+
if (typeof options !== 'object') {
196+
throw new TypeError('Channel options must be an object');
207197
}
208198
}
209199
this.originalTarget = target;

packages/grpc-js/src/server.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,10 @@ export class Server {
347347
};
348348
}
349349

350+
const deferredCallback = (error: Error | null, port: number) => {
351+
process.nextTick(() => callback(error, port));
352+
}
353+
350354
const setupServer = (): http2.Http2Server | http2.Http2SecureServer => {
351355
let http2Server: http2.Http2Server | http2.Http2SecureServer;
352356
if (creds._isSecure()) {
@@ -388,6 +392,7 @@ export class Server {
388392
const http2Server = setupServer();
389393
return new Promise<number | Error>((resolve, reject) => {
390394
function onError(err: Error): void {
395+
trace('Failed to bind ' + subchannelAddressToString(address) + ' with error ' + err.message);
391396
resolve(err);
392397
}
393398

@@ -463,6 +468,7 @@ export class Server {
463468
const http2Server = setupServer();
464469
return new Promise<BindResult>((resolve, reject) => {
465470
function onError(err: Error): void {
471+
trace('Failed to bind ' + subchannelAddressToString(address) + ' with error ' + err.message);
466472
resolve(bindWildcardPort(addressList.slice(1)));
467473
}
468474

@@ -518,7 +524,7 @@ export class Server {
518524
// We only want one resolution result. Discard all future results
519525
resolverListener.onSuccessfulResolution = () => {};
520526
if (addressList.length === 0) {
521-
callback(new Error(`No addresses resolved for port ${port}`), 0);
527+
deferredCallback(new Error(`No addresses resolved for port ${port}`), 0);
522528
return;
523529
}
524530
let bindResultPromise: Promise<BindResult>;
@@ -541,26 +547,26 @@ export class Server {
541547
if (bindResult.count === 0) {
542548
const errorString = `No address added out of total ${addressList.length} resolved`;
543549
logging.log(LogVerbosity.ERROR, errorString);
544-
callback(new Error(errorString), 0);
550+
deferredCallback(new Error(errorString), 0);
545551
} else {
546552
if (bindResult.count < addressList.length) {
547553
logging.log(
548554
LogVerbosity.INFO,
549555
`WARNING Only ${bindResult.count} addresses added out of total ${addressList.length} resolved`
550556
);
551557
}
552-
callback(null, bindResult.port);
558+
deferredCallback(null, bindResult.port);
553559
}
554560
},
555561
(error) => {
556562
const errorString = `No address added out of total ${addressList.length} resolved`;
557563
logging.log(LogVerbosity.ERROR, errorString);
558-
callback(new Error(errorString), 0);
564+
deferredCallback(new Error(errorString), 0);
559565
}
560566
);
561567
},
562568
onError: (error) => {
563-
callback(new Error(error.details), 0);
569+
deferredCallback(new Error(error.details), 0);
564570
},
565571
};
566572

0 commit comments

Comments
 (0)