mirror of https://github.com/grpc/grpc-node.git
Merge pull request #2910 from murgatroid99/grpc-js_1.12_upmerge
Merge 1.12.x into master
This commit is contained in:
commit
46a5e517ec
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@grpc/grpc-js-xds",
|
"name": "@grpc/grpc-js-xds",
|
||||||
"version": "1.12.0",
|
"version": "1.12.2",
|
||||||
"description": "Plugin for @grpc/grpc-js. Adds the xds:// URL scheme and associated features.",
|
"description": "Plugin for @grpc/grpc-js. Adds the xds:// URL scheme and associated features.",
|
||||||
"main": "build/src/index.js",
|
"main": "build/src/index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@grpc/grpc-js",
|
"name": "@grpc/grpc-js",
|
||||||
"version": "1.12.5",
|
"version": "1.12.6",
|
||||||
"description": "gRPC Library for Node - pure JS implementation",
|
"description": "gRPC Library for Node - pure JS implementation",
|
||||||
"homepage": "https://grpc.io/",
|
"homepage": "https://grpc.io/",
|
||||||
"repository": "https://github.com/grpc/grpc-node/tree/master/packages/grpc-js",
|
"repository": "https://github.com/grpc/grpc-node/tree/master/packages/grpc-js",
|
||||||
|
|
|
@ -125,10 +125,13 @@ class ChannelSubchannelWrapper
|
||||||
) => {
|
) => {
|
||||||
channel.throttleKeepalive(keepaliveTime);
|
channel.throttleKeepalive(keepaliveTime);
|
||||||
};
|
};
|
||||||
childSubchannel.addConnectivityStateListener(this.subchannelStateListener);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ref(): void {
|
ref(): void {
|
||||||
|
if (this.refCount === 0) {
|
||||||
|
this.child.addConnectivityStateListener(this.subchannelStateListener);
|
||||||
|
this.channel.addWrappedSubchannel(this);
|
||||||
|
}
|
||||||
this.child.ref();
|
this.child.ref();
|
||||||
this.refCount += 1;
|
this.refCount += 1;
|
||||||
}
|
}
|
||||||
|
@ -160,6 +163,25 @@ class ShutdownPicker implements Picker {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SUBCHANNEL_ARGS_EXCLUDE_KEY_PREFIX = 'grpc.internal.no_subchannel';
|
export const SUBCHANNEL_ARGS_EXCLUDE_KEY_PREFIX = 'grpc.internal.no_subchannel';
|
||||||
|
class ChannelzInfoTracker {
|
||||||
|
readonly trace = new ChannelzTrace();
|
||||||
|
readonly callTracker = new ChannelzCallTracker();
|
||||||
|
readonly childrenTracker = new ChannelzChildrenTracker();
|
||||||
|
state: ConnectivityState = ConnectivityState.IDLE;
|
||||||
|
constructor(private target: string) {}
|
||||||
|
|
||||||
|
getChannelzInfoCallback(): () => ChannelInfo {
|
||||||
|
return () => {
|
||||||
|
return {
|
||||||
|
target: this.target,
|
||||||
|
state: this.state,
|
||||||
|
trace: this.trace,
|
||||||
|
callTracker: this.callTracker,
|
||||||
|
children: this.childrenTracker.getChildLists()
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class InternalChannel {
|
export class InternalChannel {
|
||||||
private readonly resolvingLoadBalancer: ResolvingLoadBalancer;
|
private readonly resolvingLoadBalancer: ResolvingLoadBalancer;
|
||||||
|
@ -181,9 +203,10 @@ export class InternalChannel {
|
||||||
* event loop open while there are any pending calls for the channel that
|
* event loop open while there are any pending calls for the channel that
|
||||||
* have not yet been assigned to specific subchannels. In other words,
|
* have not yet been assigned to specific subchannels. In other words,
|
||||||
* the invariant is that callRefTimer is reffed if and only if pickQueue
|
* the invariant is that callRefTimer is reffed if and only if pickQueue
|
||||||
* is non-empty.
|
* is non-empty. In addition, the timer is null while the state is IDLE or
|
||||||
|
* SHUTDOWN and there are no pending calls.
|
||||||
*/
|
*/
|
||||||
private readonly callRefTimer: NodeJS.Timeout;
|
private callRefTimer: NodeJS.Timeout | null = null;
|
||||||
private configSelector: ConfigSelector | null = null;
|
private configSelector: ConfigSelector | null = null;
|
||||||
/**
|
/**
|
||||||
* This is the error from the name resolver if it failed most recently. It
|
* This is the error from the name resolver if it failed most recently. It
|
||||||
|
@ -205,11 +228,8 @@ export class InternalChannel {
|
||||||
|
|
||||||
// Channelz info
|
// Channelz info
|
||||||
private readonly channelzEnabled: boolean = true;
|
private readonly channelzEnabled: boolean = true;
|
||||||
private readonly originalTarget: string;
|
|
||||||
private readonly channelzRef: ChannelRef;
|
private readonly channelzRef: ChannelRef;
|
||||||
private readonly channelzTrace: ChannelzTrace;
|
private readonly channelzInfoTracker: ChannelzInfoTracker;
|
||||||
private readonly callTracker = new ChannelzCallTracker();
|
|
||||||
private readonly childrenTracker = new ChannelzChildrenTracker();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Randomly generated ID to be passed to the config selector, for use by
|
* Randomly generated ID to be passed to the config selector, for use by
|
||||||
|
@ -238,7 +258,7 @@ export class InternalChannel {
|
||||||
throw new TypeError('Channel options must be an object');
|
throw new TypeError('Channel options must be an object');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.originalTarget = target;
|
this.channelzInfoTracker = new ChannelzInfoTracker(target);
|
||||||
const originalTargetUri = parseUri(target);
|
const originalTargetUri = parseUri(target);
|
||||||
if (originalTargetUri === null) {
|
if (originalTargetUri === null) {
|
||||||
throw new Error(`Could not parse target name "${target}"`);
|
throw new Error(`Could not parse target name "${target}"`);
|
||||||
|
@ -252,21 +272,17 @@ export class InternalChannel {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.callRefTimer = setInterval(() => {}, MAX_TIMEOUT_TIME);
|
|
||||||
this.callRefTimer.unref?.();
|
|
||||||
|
|
||||||
if (this.options['grpc.enable_channelz'] === 0) {
|
if (this.options['grpc.enable_channelz'] === 0) {
|
||||||
this.channelzEnabled = false;
|
this.channelzEnabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.channelzTrace = new ChannelzTrace();
|
|
||||||
this.channelzRef = registerChannelzChannel(
|
this.channelzRef = registerChannelzChannel(
|
||||||
target,
|
target,
|
||||||
() => this.getChannelzInfo(),
|
this.channelzInfoTracker.getChannelzInfoCallback(),
|
||||||
this.channelzEnabled
|
this.channelzEnabled
|
||||||
);
|
);
|
||||||
if (this.channelzEnabled) {
|
if (this.channelzEnabled) {
|
||||||
this.channelzTrace.addTrace('CT_INFO', 'Channel created');
|
this.channelzInfoTracker.trace.addTrace('CT_INFO', 'Channel created');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.options['grpc.default_authority']) {
|
if (this.options['grpc.default_authority']) {
|
||||||
|
@ -312,7 +328,7 @@ export class InternalChannel {
|
||||||
);
|
);
|
||||||
subchannel.throttleKeepalive(this.keepaliveTime);
|
subchannel.throttleKeepalive(this.keepaliveTime);
|
||||||
if (this.channelzEnabled) {
|
if (this.channelzEnabled) {
|
||||||
this.channelzTrace.addTrace(
|
this.channelzInfoTracker.trace.addTrace(
|
||||||
'CT_INFO',
|
'CT_INFO',
|
||||||
'Created subchannel or used existing subchannel',
|
'Created subchannel or used existing subchannel',
|
||||||
subchannel.getChannelzRef()
|
subchannel.getChannelzRef()
|
||||||
|
@ -322,7 +338,6 @@ export class InternalChannel {
|
||||||
subchannel,
|
subchannel,
|
||||||
this
|
this
|
||||||
);
|
);
|
||||||
this.wrappedSubchannels.add(wrappedSubchannel);
|
|
||||||
return wrappedSubchannel;
|
return wrappedSubchannel;
|
||||||
},
|
},
|
||||||
updateState: (connectivityState: ConnectivityState, picker: Picker) => {
|
updateState: (connectivityState: ConnectivityState, picker: Picker) => {
|
||||||
|
@ -345,12 +360,12 @@ export class InternalChannel {
|
||||||
},
|
},
|
||||||
addChannelzChild: (child: ChannelRef | SubchannelRef) => {
|
addChannelzChild: (child: ChannelRef | SubchannelRef) => {
|
||||||
if (this.channelzEnabled) {
|
if (this.channelzEnabled) {
|
||||||
this.childrenTracker.refChild(child);
|
this.channelzInfoTracker.childrenTracker.refChild(child);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
removeChannelzChild: (child: ChannelRef | SubchannelRef) => {
|
removeChannelzChild: (child: ChannelRef | SubchannelRef) => {
|
||||||
if (this.channelzEnabled) {
|
if (this.channelzEnabled) {
|
||||||
this.childrenTracker.unrefChild(child);
|
this.channelzInfoTracker.childrenTracker.unrefChild(child);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -372,7 +387,7 @@ export class InternalChannel {
|
||||||
RETRY_THROTTLER_MAP.delete(this.getTarget());
|
RETRY_THROTTLER_MAP.delete(this.getTarget());
|
||||||
}
|
}
|
||||||
if (this.channelzEnabled) {
|
if (this.channelzEnabled) {
|
||||||
this.channelzTrace.addTrace(
|
this.channelzInfoTracker.trace.addTrace(
|
||||||
'CT_INFO',
|
'CT_INFO',
|
||||||
'Address resolution succeeded'
|
'Address resolution succeeded'
|
||||||
);
|
);
|
||||||
|
@ -395,7 +410,7 @@ export class InternalChannel {
|
||||||
},
|
},
|
||||||
status => {
|
status => {
|
||||||
if (this.channelzEnabled) {
|
if (this.channelzEnabled) {
|
||||||
this.channelzTrace.addTrace(
|
this.channelzInfoTracker.trace.addTrace(
|
||||||
'CT_WARNING',
|
'CT_WARNING',
|
||||||
'Address resolution failed with code ' +
|
'Address resolution failed with code ' +
|
||||||
status.code +
|
status.code +
|
||||||
|
@ -447,16 +462,6 @@ export class InternalChannel {
|
||||||
this.lastActivityTimestamp = new Date();
|
this.lastActivityTimestamp = new Date();
|
||||||
}
|
}
|
||||||
|
|
||||||
private getChannelzInfo(): ChannelInfo {
|
|
||||||
return {
|
|
||||||
target: this.originalTarget,
|
|
||||||
state: this.connectivityState,
|
|
||||||
trace: this.channelzTrace,
|
|
||||||
callTracker: this.callTracker,
|
|
||||||
children: this.childrenTracker.getChildLists(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private trace(text: string, verbosityOverride?: LogVerbosity) {
|
private trace(text: string, verbosityOverride?: LogVerbosity) {
|
||||||
trace(
|
trace(
|
||||||
verbosityOverride ?? LogVerbosity.DEBUG,
|
verbosityOverride ?? LogVerbosity.DEBUG,
|
||||||
|
@ -466,6 +471,9 @@ export class InternalChannel {
|
||||||
}
|
}
|
||||||
|
|
||||||
private callRefTimerRef() {
|
private callRefTimerRef() {
|
||||||
|
if (!this.callRefTimer) {
|
||||||
|
this.callRefTimer = setInterval(() => {}, MAX_TIMEOUT_TIME)
|
||||||
|
}
|
||||||
// If the hasRef function does not exist, always run the code
|
// If the hasRef function does not exist, always run the code
|
||||||
if (!this.callRefTimer.hasRef?.()) {
|
if (!this.callRefTimer.hasRef?.()) {
|
||||||
this.trace(
|
this.trace(
|
||||||
|
@ -479,15 +487,15 @@ export class InternalChannel {
|
||||||
}
|
}
|
||||||
|
|
||||||
private callRefTimerUnref() {
|
private callRefTimerUnref() {
|
||||||
// If the hasRef function does not exist, always run the code
|
// If the timer or the hasRef function does not exist, always run the code
|
||||||
if (!this.callRefTimer.hasRef || this.callRefTimer.hasRef()) {
|
if (!this.callRefTimer?.hasRef || this.callRefTimer.hasRef()) {
|
||||||
this.trace(
|
this.trace(
|
||||||
'callRefTimer.unref | configSelectionQueue.length=' +
|
'callRefTimer.unref | configSelectionQueue.length=' +
|
||||||
this.configSelectionQueue.length +
|
this.configSelectionQueue.length +
|
||||||
' pickQueue.length=' +
|
' pickQueue.length=' +
|
||||||
this.pickQueue.length
|
this.pickQueue.length
|
||||||
);
|
);
|
||||||
this.callRefTimer.unref?.();
|
this.callRefTimer?.unref?.();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -516,12 +524,13 @@ export class InternalChannel {
|
||||||
ConnectivityState[newState]
|
ConnectivityState[newState]
|
||||||
);
|
);
|
||||||
if (this.channelzEnabled) {
|
if (this.channelzEnabled) {
|
||||||
this.channelzTrace.addTrace(
|
this.channelzInfoTracker.trace.addTrace(
|
||||||
'CT_INFO',
|
'CT_INFO',
|
||||||
'Connectivity state change to ' + ConnectivityState[newState]
|
'Connectivity state change to ' + ConnectivityState[newState]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
this.connectivityState = newState;
|
this.connectivityState = newState;
|
||||||
|
this.channelzInfoTracker.state = newState;
|
||||||
const watchersCopy = this.connectivityStateWatchers.slice();
|
const watchersCopy = this.connectivityStateWatchers.slice();
|
||||||
for (const watcherObject of watchersCopy) {
|
for (const watcherObject of watchersCopy) {
|
||||||
if (newState !== watcherObject.currentState) {
|
if (newState !== watcherObject.currentState) {
|
||||||
|
@ -546,6 +555,10 @@ export class InternalChannel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addWrappedSubchannel(wrappedSubchannel: ChannelSubchannelWrapper) {
|
||||||
|
this.wrappedSubchannels.add(wrappedSubchannel);
|
||||||
|
}
|
||||||
|
|
||||||
removeWrappedSubchannel(wrappedSubchannel: ChannelSubchannelWrapper) {
|
removeWrappedSubchannel(wrappedSubchannel: ChannelSubchannelWrapper) {
|
||||||
this.wrappedSubchannels.delete(wrappedSubchannel);
|
this.wrappedSubchannels.delete(wrappedSubchannel);
|
||||||
}
|
}
|
||||||
|
@ -598,6 +611,10 @@ export class InternalChannel {
|
||||||
clearTimeout(this.idleTimer);
|
clearTimeout(this.idleTimer);
|
||||||
this.idleTimer = null;
|
this.idleTimer = null;
|
||||||
}
|
}
|
||||||
|
if (this.callRefTimer) {
|
||||||
|
clearInterval(this.callRefTimer);
|
||||||
|
this.callRefTimer = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private startIdleTimeout(timeoutMs: number) {
|
private startIdleTimeout(timeoutMs: number) {
|
||||||
|
@ -641,7 +658,7 @@ export class InternalChannel {
|
||||||
|
|
||||||
private onCallStart() {
|
private onCallStart() {
|
||||||
if (this.channelzEnabled) {
|
if (this.channelzEnabled) {
|
||||||
this.callTracker.addCallStarted();
|
this.channelzInfoTracker.callTracker.addCallStarted();
|
||||||
}
|
}
|
||||||
this.callCount += 1;
|
this.callCount += 1;
|
||||||
}
|
}
|
||||||
|
@ -649,9 +666,9 @@ export class InternalChannel {
|
||||||
private onCallEnd(status: StatusObject) {
|
private onCallEnd(status: StatusObject) {
|
||||||
if (this.channelzEnabled) {
|
if (this.channelzEnabled) {
|
||||||
if (status.code === Status.OK) {
|
if (status.code === Status.OK) {
|
||||||
this.callTracker.addCallSucceeded();
|
this.channelzInfoTracker.callTracker.addCallSucceeded();
|
||||||
} else {
|
} else {
|
||||||
this.callTracker.addCallFailed();
|
this.channelzInfoTracker.callTracker.addCallFailed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.callCount -= 1;
|
this.callCount -= 1;
|
||||||
|
@ -755,7 +772,9 @@ export class InternalChannel {
|
||||||
call.cancelWithStatus(Status.UNAVAILABLE, 'Channel closed before call started');
|
call.cancelWithStatus(Status.UNAVAILABLE, 'Channel closed before call started');
|
||||||
}
|
}
|
||||||
this.pickQueue = [];
|
this.pickQueue = [];
|
||||||
clearInterval(this.callRefTimer);
|
if (this.callRefTimer) {
|
||||||
|
clearInterval(this.callRefTimer);
|
||||||
|
}
|
||||||
if (this.idleTimer) {
|
if (this.idleTimer) {
|
||||||
clearTimeout(this.idleTimer);
|
clearTimeout(this.idleTimer);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue