mirror of https://github.com/grpc/grpc-node.git
grpc-js-xds: Fix behavior when channel goes IDLE
This commit is contained in:
parent
c8cbffa066
commit
c8b9a45bc9
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@grpc/grpc-js-xds",
|
||||
"version": "1.9.0",
|
||||
"version": "1.9.1",
|
||||
"description": "Plugin for @grpc/grpc-js. Adds the xds:// URL scheme and associated features.",
|
||||
"main": "build/src/index.js",
|
||||
"scripts": {
|
||||
|
|
|
@ -213,7 +213,7 @@ function getPredicateForMatcher(routeMatch: RouteMatch__Output): Matcher {
|
|||
* the ServiceConfig definition. The difference is that the protobuf message
|
||||
* defines seconds as a long, which is represented as a string in JavaScript,
|
||||
* and the one used in the service config defines it as a number.
|
||||
* @param duration
|
||||
* @param duration
|
||||
*/
|
||||
function protoDurationToDuration(duration: Duration__Output): Duration {
|
||||
return {
|
||||
|
@ -235,7 +235,7 @@ function getDefaultRetryMaxInterval(baseInterval: string): string {
|
|||
/**
|
||||
* Encode a text string as a valid path of a URI, as specified in RFC-3986 section 3.3
|
||||
* @param uriPath A value representing an unencoded URI path
|
||||
* @returns
|
||||
* @returns
|
||||
*/
|
||||
function encodeURIPath(uriPath: string): string {
|
||||
return uriPath.replace(/[^A-Za-z0-9._~!$&^()*+,;=/-]/g, substring => encodeURIComponent(substring));
|
||||
|
@ -447,7 +447,7 @@ class XdsResolver implements Resolver {
|
|||
}
|
||||
}
|
||||
}
|
||||
let retryPolicy: RetryPolicy | undefined = undefined;
|
||||
let retryPolicy: RetryPolicy | undefined = undefined;
|
||||
if (EXPERIMENTAL_RETRY) {
|
||||
const retryConfig = route.route!.retry_policy ?? virtualHost.retry_policy;
|
||||
if (retryConfig) {
|
||||
|
@ -458,10 +458,10 @@ class XdsResolver implements Resolver {
|
|||
}
|
||||
}
|
||||
if (retryableStatusCodes.length > 0) {
|
||||
const baseInterval = retryConfig.retry_back_off?.base_interval ?
|
||||
protoDurationToSecondsString(retryConfig.retry_back_off.base_interval) :
|
||||
const baseInterval = retryConfig.retry_back_off?.base_interval ?
|
||||
protoDurationToSecondsString(retryConfig.retry_back_off.base_interval) :
|
||||
DEFAULT_RETRY_BASE_INTERVAL;
|
||||
const maxInterval = retryConfig.retry_back_off?.max_interval ?
|
||||
const maxInterval = retryConfig.retry_back_off?.max_interval ?
|
||||
protoDurationToSecondsString(retryConfig.retry_back_off.max_interval) :
|
||||
getDefaultRetryMaxInterval(baseInterval);
|
||||
retryPolicy = {
|
||||
|
@ -664,9 +664,11 @@ class XdsResolver implements Resolver {
|
|||
destroy() {
|
||||
if (this.listenerResourceName) {
|
||||
ListenerResourceType.cancelWatch(this.xdsClient, this.listenerResourceName, this.ldsWatcher);
|
||||
this.isLdsWatcherActive = false;
|
||||
}
|
||||
if (this.latestRouteConfigName) {
|
||||
RouteConfigurationResourceType.cancelWatch(this.xdsClient, this.latestRouteConfigName, this.rdsWatcher);
|
||||
this.latestRouteConfigName = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
import { credentials, loadPackageDefinition, ServiceError } from "@grpc/grpc-js";
|
||||
import { ChannelOptions, credentials, loadPackageDefinition, ServiceError } from "@grpc/grpc-js";
|
||||
import { loadSync } from "@grpc/proto-loader";
|
||||
import { ProtoGrpcType } from "./generated/echo";
|
||||
import { EchoTestServiceClient } from "./generated/grpc/testing/EchoTestService";
|
||||
|
@ -44,14 +44,14 @@ export class XdsTestClient {
|
|||
private client: EchoTestServiceClient;
|
||||
private callInterval: NodeJS.Timer;
|
||||
|
||||
constructor(target: string, bootstrapInfo: string) {
|
||||
this.client = new loadedProtos.grpc.testing.EchoTestService(target, credentials.createInsecure(), {[BOOTSTRAP_CONFIG_KEY]: bootstrapInfo});
|
||||
constructor(target: string, bootstrapInfo: string, options?: ChannelOptions) {
|
||||
this.client = new loadedProtos.grpc.testing.EchoTestService(target, credentials.createInsecure(), {...options, [BOOTSTRAP_CONFIG_KEY]: bootstrapInfo});
|
||||
this.callInterval = setInterval(() => {}, 0);
|
||||
clearInterval(this.callInterval);
|
||||
}
|
||||
|
||||
static createFromServer(targetName: string, xdsServer: XdsServer) {
|
||||
return new XdsTestClient(`xds:///${targetName}`, xdsServer.getBootstrapInfoString());
|
||||
static createFromServer(targetName: string, xdsServer: XdsServer, options?: ChannelOptions) {
|
||||
return new XdsTestClient(`xds:///${targetName}`, xdsServer.getBootstrapInfoString(), options);
|
||||
}
|
||||
|
||||
startCalls(interval: number) {
|
||||
|
@ -98,4 +98,8 @@ export class XdsTestClient {
|
|||
}
|
||||
sendInner(count, callback);
|
||||
}
|
||||
|
||||
getConnectivityState() {
|
||||
return this.client.getChannel().getConnectivityState(false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import { XdsServer } from "./xds-server";
|
|||
|
||||
import { register } from "../src";
|
||||
import assert = require("assert");
|
||||
import { connectivityState } from "@grpc/grpc-js";
|
||||
|
||||
register();
|
||||
|
||||
|
@ -60,4 +61,34 @@ describe('core xDS functionality', () => {
|
|||
}, reason => done(reason));
|
||||
}, reason => done(reason));
|
||||
});
|
||||
it('should be able to enter and exit idle', function(done) {
|
||||
this.timeout(5000);
|
||||
const cluster = new FakeEdsCluster('cluster1', 'endpoint1', [{backends: [new Backend()], locality:{region: 'region1'}}]);
|
||||
const routeGroup = new FakeRouteGroup('listener1', 'route1', [{cluster: cluster}]);
|
||||
routeGroup.startAllBackends().then(() => {
|
||||
xdsServer.setEdsResource(cluster.getEndpointConfig());
|
||||
xdsServer.setCdsResource(cluster.getClusterConfig());
|
||||
xdsServer.setRdsResource(routeGroup.getRouteConfiguration());
|
||||
xdsServer.setLdsResource(routeGroup.getListener());
|
||||
xdsServer.addResponseListener((typeUrl, responseState) => {
|
||||
if (responseState.state === 'NACKED') {
|
||||
client.stopCalls();
|
||||
assert.fail(`Client NACKED ${typeUrl} resource with message ${responseState.errorMessage}`);
|
||||
}
|
||||
})
|
||||
client = XdsTestClient.createFromServer('listener1', xdsServer, {
|
||||
'grpc.client_idle_timeout_ms': 1000,
|
||||
});
|
||||
client.sendOneCall(error => {
|
||||
assert.ifError(error);
|
||||
assert.strictEqual(client.getConnectivityState(), connectivityState.READY);
|
||||
setTimeout(() => {
|
||||
assert.strictEqual(client.getConnectivityState(), connectivityState.IDLE);
|
||||
client.sendOneCall(error => {
|
||||
done(error);
|
||||
})
|
||||
}, 1100);
|
||||
});
|
||||
}, reason => done(reason));
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue