diff --git a/packages/grpc-js/package.json b/packages/grpc-js/package.json index c068b0e9..4d4ffdb7 100644 --- a/packages/grpc-js/package.json +++ b/packages/grpc-js/package.json @@ -1,6 +1,6 @@ { "name": "@grpc/grpc-js", - "version": "1.8.14", + "version": "1.8.18", "description": "gRPC Library for Node - pure JS implementation", "homepage": "https://grpc.io/", "repository": "https://github.com/grpc/grpc-node/tree/master/packages/grpc-js", diff --git a/packages/grpc-js/src/channel-credentials.ts b/packages/grpc-js/src/channel-credentials.ts index dc6069c8..5c18bb4a 100644 --- a/packages/grpc-js/src/channel-credentials.ts +++ b/packages/grpc-js/src/channel-credentials.ts @@ -43,14 +43,6 @@ export type CheckServerIdentityCallback = ( cert: PeerCertificate ) => Error | undefined; -function bufferOrNullEqual(buf1: Buffer | null, buf2: Buffer | null) { - if (buf1 === null && buf2 === null) { - return true; - } else { - return buf1 !== null && buf2 !== null && buf1.equals(buf2); - } -} - /** * Additional peer verification options that can be set when creating * SSL credentials. @@ -199,7 +191,7 @@ class SecureChannelCredentialsImpl extends ChannelCredentials { ) { super(); this.connectionOptions = { - secureContext, + secureContext }; // Node asserts that this option is a function, so we cannot pass undefined if (verifyOptions?.checkServerIdentity) { @@ -228,9 +220,8 @@ class SecureChannelCredentialsImpl extends ChannelCredentials { if (other instanceof SecureChannelCredentialsImpl) { return ( this.secureContext === other.secureContext && - this.verifyOptions.checkServerIdentity === - other.verifyOptions.checkServerIdentity - ); + this.verifyOptions.checkServerIdentity === other.verifyOptions.checkServerIdentity + ); } else { return false; } diff --git a/packages/grpc-js/src/client-interceptors.ts b/packages/grpc-js/src/client-interceptors.ts index 56175ed8..4f53d177 100644 --- a/packages/grpc-js/src/client-interceptors.ts +++ b/packages/grpc-js/src/client-interceptors.ts @@ -32,7 +32,6 @@ import { import { Status } from './constants'; import { Channel } from './channel'; import { CallOptions } from './client'; -import { CallCredentials } from './call-credentials'; import { ClientMethodDefinition } from './make-client'; import { getErrorMessage } from './error'; diff --git a/packages/grpc-js/src/client.ts b/packages/grpc-js/src/client.ts index 61f98666..312ed55a 100644 --- a/packages/grpc-js/src/client.ts +++ b/packages/grpc-js/src/client.ts @@ -322,7 +322,7 @@ export class Client { emitter.call = call; let responseMessage: ResponseType | null = null; let receivedStatus = false; - const callerStackError = new Error(); + let callerStackError: Error | null = new Error(); call.start(callProperties.metadata, { onReceiveMetadata: metadata => { emitter.emit('metadata', metadata); @@ -341,24 +341,22 @@ export class Client { receivedStatus = true; if (status.code === Status.OK) { if (responseMessage === null) { - const callerStack = getErrorStackString(callerStackError); - callProperties.callback!( - callErrorFromStatus( - { - code: Status.INTERNAL, - details: 'No message received', - metadata: status.metadata, - }, - callerStack - ) - ); + const callerStack = getErrorStackString(callerStackError!); + callProperties.callback!(callErrorFromStatus({ + code: Status.INTERNAL, + details: 'No message received', + metadata: status.metadata + }, callerStack)); } else { callProperties.callback!(null, responseMessage); } } else { - const callerStack = getErrorStackString(callerStackError); + const callerStack = getErrorStackString(callerStackError!); callProperties.callback!(callErrorFromStatus(status, callerStack)); } + /* Avoid retaining the callerStackError object in the call context of + * the status event handler. */ + callerStackError = null; emitter.emit('status', status); }, }); @@ -452,7 +450,7 @@ export class Client { emitter.call = call; let responseMessage: ResponseType | null = null; let receivedStatus = false; - const callerStackError = new Error(); + let callerStackError: Error | null = new Error(); call.start(callProperties.metadata, { onReceiveMetadata: metadata => { emitter.emit('metadata', metadata); @@ -471,24 +469,22 @@ export class Client { receivedStatus = true; if (status.code === Status.OK) { if (responseMessage === null) { - const callerStack = getErrorStackString(callerStackError); - callProperties.callback!( - callErrorFromStatus( - { - code: Status.INTERNAL, - details: 'No message received', - metadata: status.metadata, - }, - callerStack - ) - ); + const callerStack = getErrorStackString(callerStackError!); + callProperties.callback!(callErrorFromStatus({ + code: Status.INTERNAL, + details: 'No message received', + metadata: status.metadata + }, callerStack)); } else { callProperties.callback!(null, responseMessage); } } else { - const callerStack = getErrorStackString(callerStackError); + const callerStack = getErrorStackString(callerStackError!); callProperties.callback!(callErrorFromStatus(status, callerStack)); } + /* Avoid retaining the callerStackError object in the call context of + * the status event handler. */ + callerStackError = null; emitter.emit('status', status); }, }); @@ -585,7 +581,7 @@ export class Client { * call after that. */ stream.call = call; let receivedStatus = false; - const callerStackError = new Error(); + let callerStackError: Error | null = new Error(); call.start(callProperties.metadata, { onReceiveMetadata(metadata: Metadata) { stream.emit('metadata', metadata); @@ -601,9 +597,12 @@ export class Client { receivedStatus = true; stream.push(null); if (status.code !== Status.OK) { - const callerStack = getErrorStackString(callerStackError); + const callerStack = getErrorStackString(callerStackError!); stream.emit('error', callErrorFromStatus(status, callerStack)); } + /* Avoid retaining the callerStackError object in the call context of + * the status event handler. */ + callerStackError = null; stream.emit('status', status); }, }); @@ -677,7 +676,7 @@ export class Client { * call after that. */ stream.call = call; let receivedStatus = false; - const callerStackError = new Error(); + let callerStackError: Error | null = new Error(); call.start(callProperties.metadata, { onReceiveMetadata(metadata: Metadata) { stream.emit('metadata', metadata); @@ -692,9 +691,12 @@ export class Client { receivedStatus = true; stream.push(null); if (status.code !== Status.OK) { - const callerStack = getErrorStackString(callerStackError); + const callerStack = getErrorStackString(callerStackError!); stream.emit('error', callErrorFromStatus(status, callerStack)); } + /* Avoid retaining the callerStackError object in the call context of + * the status event handler. */ + callerStackError = null; stream.emit('status', status); }, }); diff --git a/packages/grpc-js/src/compression-filter.ts b/packages/grpc-js/src/compression-filter.ts index 3fd5604c..87c9db99 100644 --- a/packages/grpc-js/src/compression-filter.ts +++ b/packages/grpc-js/src/compression-filter.ts @@ -305,13 +305,9 @@ export class CompressionFilter extends BaseFilter implements Filter { } export class CompressionFilterFactory - implements FilterFactory -{ - private sharedFilterConfig: SharedCompressionFilterConfig = {}; - constructor( - private readonly channel: Channel, - private readonly options: ChannelOptions - ) {} + implements FilterFactory { + private sharedFilterConfig: SharedCompressionFilterConfig = {}; + constructor(channel: Channel, private readonly options: ChannelOptions) {} createFilter(): CompressionFilter { return new CompressionFilter(this.options, this.sharedFilterConfig); } diff --git a/packages/grpc-js/src/generated/grpc/channelz/v1/ChannelConnectivityState.ts b/packages/grpc-js/src/generated/grpc/channelz/v1/ChannelConnectivityState.ts index be34ab98..78fb0693 100644 --- a/packages/grpc-js/src/generated/grpc/channelz/v1/ChannelConnectivityState.ts +++ b/packages/grpc-js/src/generated/grpc/channelz/v1/ChannelConnectivityState.ts @@ -3,21 +3,37 @@ // Original file: proto/channelz.proto -export enum _grpc_channelz_v1_ChannelConnectivityState_State { - UNKNOWN = 0, - IDLE = 1, - CONNECTING = 2, - READY = 3, - TRANSIENT_FAILURE = 4, - SHUTDOWN = 5, -} +export const _grpc_channelz_v1_ChannelConnectivityState_State = { + UNKNOWN: 'UNKNOWN', + IDLE: 'IDLE', + CONNECTING: 'CONNECTING', + READY: 'READY', + TRANSIENT_FAILURE: 'TRANSIENT_FAILURE', + SHUTDOWN: 'SHUTDOWN', +} as const; + +export type _grpc_channelz_v1_ChannelConnectivityState_State = + | 'UNKNOWN' + | 0 + | 'IDLE' + | 1 + | 'CONNECTING' + | 2 + | 'READY' + | 3 + | 'TRANSIENT_FAILURE' + | 4 + | 'SHUTDOWN' + | 5 + +export type _grpc_channelz_v1_ChannelConnectivityState_State__Output = typeof _grpc_channelz_v1_ChannelConnectivityState_State[keyof typeof _grpc_channelz_v1_ChannelConnectivityState_State] /** * These come from the specified states in this document: * https://github.com/grpc/grpc/blob/master/doc/connectivity-semantics-and-api.md */ export interface ChannelConnectivityState { - 'state'?: (_grpc_channelz_v1_ChannelConnectivityState_State | keyof typeof _grpc_channelz_v1_ChannelConnectivityState_State); + 'state'?: (_grpc_channelz_v1_ChannelConnectivityState_State); } /** @@ -25,5 +41,5 @@ export interface ChannelConnectivityState { * https://github.com/grpc/grpc/blob/master/doc/connectivity-semantics-and-api.md */ export interface ChannelConnectivityState__Output { - 'state': (keyof typeof _grpc_channelz_v1_ChannelConnectivityState_State); + 'state': (_grpc_channelz_v1_ChannelConnectivityState_State__Output); } diff --git a/packages/grpc-js/src/generated/grpc/channelz/v1/ChannelTraceEvent.ts b/packages/grpc-js/src/generated/grpc/channelz/v1/ChannelTraceEvent.ts index 24b97fbc..403e4f12 100644 --- a/packages/grpc-js/src/generated/grpc/channelz/v1/ChannelTraceEvent.ts +++ b/packages/grpc-js/src/generated/grpc/channelz/v1/ChannelTraceEvent.ts @@ -9,12 +9,30 @@ import type { SubchannelRef as _grpc_channelz_v1_SubchannelRef, SubchannelRef__O /** * The supported severity levels of trace events. */ -export enum _grpc_channelz_v1_ChannelTraceEvent_Severity { - CT_UNKNOWN = 0, - CT_INFO = 1, - CT_WARNING = 2, - CT_ERROR = 3, -} +export const _grpc_channelz_v1_ChannelTraceEvent_Severity = { + CT_UNKNOWN: 'CT_UNKNOWN', + CT_INFO: 'CT_INFO', + CT_WARNING: 'CT_WARNING', + CT_ERROR: 'CT_ERROR', +} as const; + +/** + * The supported severity levels of trace events. + */ +export type _grpc_channelz_v1_ChannelTraceEvent_Severity = + | 'CT_UNKNOWN' + | 0 + | 'CT_INFO' + | 1 + | 'CT_WARNING' + | 2 + | 'CT_ERROR' + | 3 + +/** + * The supported severity levels of trace events. + */ +export type _grpc_channelz_v1_ChannelTraceEvent_Severity__Output = typeof _grpc_channelz_v1_ChannelTraceEvent_Severity[keyof typeof _grpc_channelz_v1_ChannelTraceEvent_Severity] /** * A trace event is an interesting thing that happened to a channel or @@ -28,7 +46,7 @@ export interface ChannelTraceEvent { /** * the severity of the trace event */ - 'severity'?: (_grpc_channelz_v1_ChannelTraceEvent_Severity | keyof typeof _grpc_channelz_v1_ChannelTraceEvent_Severity); + 'severity'?: (_grpc_channelz_v1_ChannelTraceEvent_Severity); /** * When this event occurred. */ @@ -56,7 +74,7 @@ export interface ChannelTraceEvent__Output { /** * the severity of the trace event */ - 'severity': (keyof typeof _grpc_channelz_v1_ChannelTraceEvent_Severity); + 'severity': (_grpc_channelz_v1_ChannelTraceEvent_Severity__Output); /** * When this event occurred. */ diff --git a/packages/grpc-js/src/index.ts b/packages/grpc-js/src/index.ts index 9363a37b..adacae08 100644 --- a/packages/grpc-js/src/index.ts +++ b/packages/grpc-js/src/index.ts @@ -43,9 +43,7 @@ import { loadPackageDefinition, makeClientConstructor, MethodDefinition, - ProtobufTypeDefinition, Serialize, - ServiceClientConstructor, ServiceDefinition, } from './make-client'; import { Metadata, MetadataOptions, MetadataValue } from './metadata'; diff --git a/packages/grpc-js/src/internal-channel.ts b/packages/grpc-js/src/internal-channel.ts index 1eff3cf2..678c6224 100644 --- a/packages/grpc-js/src/internal-channel.ts +++ b/packages/grpc-js/src/internal-channel.ts @@ -20,12 +20,7 @@ import { ChannelOptions } from './channel-options'; import { ResolvingLoadBalancer } from './resolving-load-balancer'; import { SubchannelPool, getSubchannelPool } from './subchannel-pool'; import { ChannelControlHelper } from './load-balancer'; -import { - UnavailablePicker, - Picker, - PickResultType, - QueuePicker, -} from './picker'; +import { UnavailablePicker, Picker, QueuePicker } from './picker'; import { Metadata } from './metadata'; import { Status, LogVerbosity, Propagate } from './constants'; import { FilterStackFactory } from './filter-stack'; @@ -36,41 +31,19 @@ import { getDefaultAuthority, mapUriDefaultScheme, } from './resolver'; -import { trace, log } from './logging'; +import { trace } from './logging'; import { SubchannelAddress } from './subchannel-address'; import { MaxMessageSizeFilterFactory } from './max-message-size-filter'; import { mapProxyName } from './http_proxy'; -import { GrpcUri, parseUri, splitHostPort, uriToString } from './uri-parser'; +import { GrpcUri, parseUri, uriToString } from './uri-parser'; import { ServerSurfaceCall } from './server-call'; -import { Filter } from './filter'; import { ConnectivityState } from './connectivity-state'; -import { - ChannelInfo, - ChannelRef, - ChannelzCallTracker, - ChannelzChildrenTracker, - ChannelzTrace, - registerChannelzChannel, - SubchannelRef, - unregisterChannelzRef, -} from './channelz'; -import { Subchannel } from './subchannel'; +import { ChannelInfo, ChannelRef, ChannelzCallTracker, ChannelzChildrenTracker, ChannelzTrace, registerChannelzChannel, SubchannelRef, unregisterChannelzRef } from './channelz'; import { LoadBalancingCall } from './load-balancing-call'; import { CallCredentials } from './call-credentials'; -import { - Call, - CallStreamOptions, - InterceptingListener, - MessageContext, - StatusObject, -} from './call-interface'; -import { SubchannelCall } from './subchannel-call'; -import { - Deadline, - deadlineToString, - getDeadlineTimeoutString, -} from './deadline'; +import { Call, CallStreamOptions, StatusObject } from './call-interface'; +import { Deadline, deadlineToString } from './deadline'; import { ResolvingCall } from './resolving-call'; import { getNextCallNumber } from './call-number'; import { restrictControlPlaneStatusCode } from './control-plane-status'; diff --git a/packages/grpc-js/src/load-balancer-outlier-detection.ts b/packages/grpc-js/src/load-balancer-outlier-detection.ts index 0c61065e..5a67855f 100644 --- a/packages/grpc-js/src/load-balancer-outlier-detection.ts +++ b/packages/grpc-js/src/load-balancer-outlier-detection.ts @@ -24,7 +24,6 @@ import { createChildChannelControlHelper, registerLoadBalancerType, } from './experimental'; -import { BaseFilter, Filter, FilterFactory } from './filter'; import { getFirstUsableConfig, LoadBalancer, @@ -37,10 +36,7 @@ import { Picker, PickResult, PickResultType, - QueuePicker, - UnavailablePicker, } from './picker'; -import { Subchannel } from './subchannel'; import { SubchannelAddress, subchannelAddressToString, @@ -174,6 +170,9 @@ export class OutlierDetectionLoadBalancingConfig failurePercentageEjection: Partial | null, private readonly childPolicy: LoadBalancingConfig[] ) { + if (childPolicy.length > 0 && childPolicy[0].getLoadBalancerName() === 'pick_first') { + throw new Error('outlier_detection LB policy cannot have a pick_first child policy'); + } this.intervalMs = intervalMs ?? 10_000; this.baseEjectionTimeMs = baseEjectionTimeMs ?? 30_000; this.maxEjectionTimeMs = maxEjectionTimeMs ?? 300_000; diff --git a/packages/grpc-js/src/load-balancer.ts b/packages/grpc-js/src/load-balancer.ts index 8e859495..f1863878 100644 --- a/packages/grpc-js/src/load-balancer.ts +++ b/packages/grpc-js/src/load-balancer.ts @@ -16,7 +16,6 @@ */ import { ChannelOptions } from './channel-options'; -import { Subchannel } from './subchannel'; import { SubchannelAddress } from './subchannel-address'; import { ConnectivityState } from './connectivity-state'; import { Picker } from './picker'; diff --git a/packages/grpc-js/src/load-balancing-call.ts b/packages/grpc-js/src/load-balancing-call.ts index 1a97c89f..b345241c 100644 --- a/packages/grpc-js/src/load-balancing-call.ts +++ b/packages/grpc-js/src/load-balancing-call.ts @@ -26,7 +26,6 @@ import { SubchannelCall } from './subchannel-call'; import { ConnectivityState } from './connectivity-state'; import { LogVerbosity, Status } from './constants'; import { Deadline, getDeadlineTimeoutString } from './deadline'; -import { FilterStack, FilterStackFactory } from './filter-stack'; import { InternalChannel } from './internal-channel'; import { Metadata } from './metadata'; import { PickResultType } from './picker'; @@ -55,7 +54,6 @@ export class LoadBalancingCall implements Call { private pendingMessage: { context: MessageContext; message: Buffer } | null = null; private pendingHalfClose = false; - private pendingChildStatus: StatusObject | null = null; private ended = false; private serviceUrl: string; private metadata: Metadata | null = null; @@ -258,27 +256,19 @@ export class LoadBalancingCall implements Call { ); break; case PickResultType.DROP: - const { code, details } = restrictControlPlaneStatusCode( - pickResult.status!.code, - pickResult.status!.details - ); - this.outputStatus( - { code, details, metadata: pickResult.status!.metadata }, - 'DROP' - ); + const {code, details} = restrictControlPlaneStatusCode(pickResult.status!.code, pickResult.status!.details); + setImmediate(() => { + this.outputStatus({code, details, metadata: pickResult.status!.metadata}, 'DROP'); + }); break; case PickResultType.TRANSIENT_FAILURE: if (this.metadata.getOptions().waitForReady) { this.channel.queueCallForPick(this); } else { - const { code, details } = restrictControlPlaneStatusCode( - pickResult.status!.code, - pickResult.status!.details - ); - this.outputStatus( - { code, details, metadata: pickResult.status!.metadata }, - 'PROCESSED' - ); + const {code, details} = restrictControlPlaneStatusCode(pickResult.status!.code, pickResult.status!.details); + setImmediate(() => { + this.outputStatus({code, details, metadata: pickResult.status!.metadata}, 'PROCESSED'); + }); } break; case PickResultType.QUEUE: diff --git a/packages/grpc-js/src/max-message-size-filter.ts b/packages/grpc-js/src/max-message-size-filter.ts index d0f79162..9df9de8b 100644 --- a/packages/grpc-js/src/max-message-size-filter.ts +++ b/packages/grpc-js/src/max-message-size-filter.ts @@ -28,7 +28,9 @@ import { Metadata } from './metadata'; export class MaxMessageSizeFilter extends BaseFilter implements Filter { private maxSendMessageSize: number = DEFAULT_MAX_SEND_MESSAGE_LENGTH; private maxReceiveMessageSize: number = DEFAULT_MAX_RECEIVE_MESSAGE_LENGTH; - constructor(private readonly options: ChannelOptions) { + constructor( + options: ChannelOptions + ) { super(); if ('grpc.max_send_message_length' in options) { this.maxSendMessageSize = options['grpc.max_send_message_length']!; diff --git a/packages/grpc-js/src/metadata.ts b/packages/grpc-js/src/metadata.ts index f5ab6bd3..eabd2dff 100644 --- a/packages/grpc-js/src/metadata.ts +++ b/packages/grpc-js/src/metadata.ts @@ -230,11 +230,6 @@ export class Metadata { return result; } - // For compatibility with the other Metadata implementation - private _getCoreRepresentation() { - return this.internalRepr; - } - /** * This modifies the behavior of JSON.stringify to show an object * representation of the metadata map. diff --git a/packages/grpc-js/src/object-stream.ts b/packages/grpc-js/src/object-stream.ts index 946d4afe..49ef1f33 100644 --- a/packages/grpc-js/src/object-stream.ts +++ b/packages/grpc-js/src/object-stream.ts @@ -15,7 +15,7 @@ * */ -import { Duplex, Readable, Writable } from 'stream'; +import { Readable, Writable } from 'stream'; import { EmitterAugmentation1 } from './events'; /* eslint-disable @typescript-eslint/no-explicit-any */ diff --git a/packages/grpc-js/src/resolver-dns.ts b/packages/grpc-js/src/resolver-dns.ts index 7f84e0c5..6b866e94 100644 --- a/packages/grpc-js/src/resolver-dns.ts +++ b/packages/grpc-js/src/resolver-dns.ts @@ -286,7 +286,7 @@ class DnsResolver implements Resolver { } catch (err) { this.latestServiceConfigError = { code: Status.UNAVAILABLE, - details: 'Parsing service config failed', + details: `Parsing service config failed with error ${(err as Error).message}`, metadata: new Metadata(), }; } diff --git a/packages/grpc-js/src/resolver-ip.ts b/packages/grpc-js/src/resolver-ip.ts index efb0b8dc..0704131e 100644 --- a/packages/grpc-js/src/resolver-ip.ts +++ b/packages/grpc-js/src/resolver-ip.ts @@ -42,7 +42,7 @@ class IpResolver implements Resolver { private addresses: SubchannelAddress[] = []; private error: StatusObject | null = null; constructor( - private target: GrpcUri, + target: GrpcUri, private listener: ResolverListener, channelOptions: ChannelOptions ) { diff --git a/packages/grpc-js/src/resolving-call.ts b/packages/grpc-js/src/resolving-call.ts index 9c4b1891..8aa717c0 100644 --- a/packages/grpc-js/src/resolving-call.ts +++ b/packages/grpc-js/src/resolving-call.ts @@ -27,7 +27,6 @@ import { LogVerbosity, Propagate, Status } from './constants'; import { Deadline, deadlineToString, - getDeadlineTimeoutString, getRelativeTimeout, minDeadline, } from './deadline'; diff --git a/packages/grpc-js/src/resolving-load-balancer.ts b/packages/grpc-js/src/resolving-load-balancer.ts index 16533354..d49609ff 100644 --- a/packages/grpc-js/src/resolving-load-balancer.ts +++ b/packages/grpc-js/src/resolving-load-balancer.ts @@ -36,7 +36,6 @@ import { SubchannelAddress } from './subchannel-address'; import { GrpcUri, uriToString } from './uri-parser'; import { ChildLoadBalancerHandler } from './load-balancer-child-handler'; import { ChannelOptions } from './channel-options'; -import { PickFirstLoadBalancingConfig } from './load-balancer-pick-first'; const TRACER_NAME = 'resolving_load_balancer'; @@ -44,8 +43,6 @@ function trace(text: string): void { logging.trace(LogVerbosity.DEBUG, TRACER_NAME, text); } -const DEFAULT_LOAD_BALANCER_NAME = 'pick_first'; - function getDefaultConfigSelector( serviceConfig: ServiceConfig | null ): ConfigSelector { @@ -137,7 +134,7 @@ export class ResolvingLoadBalancer implements LoadBalancer { constructor( private readonly target: GrpcUri, private readonly channelControlHelper: ChannelControlHelper, - private readonly channelOptions: ChannelOptions, + channelOptions: ChannelOptions, private readonly onSuccessfulResolution: ResolutionCallback, private readonly onFailedResolution: ResolutionFailureCallback ) { diff --git a/packages/grpc-js/src/server-call.ts b/packages/grpc-js/src/server-call.ts index 0e1f94d2..934c5882 100644 --- a/packages/grpc-js/src/server-call.ts +++ b/packages/grpc-js/src/server-call.ts @@ -268,6 +268,9 @@ export class ServerDuplexStreamImpl implements ServerDuplexStream { cancelled: boolean; + /* This field appears to be unsued, but it is actually used in _final, which is assiged from + * ServerWritableStreamImpl.prototype._final below. */ + // @ts-ignore noUnusedLocals private trailingMetadata: Metadata; constructor( @@ -419,7 +422,7 @@ export class Http2ServerCallStream< constructor( private stream: http2.ServerHttp2Stream, private handler: Handler, - private options: ChannelOptions + options: ChannelOptions ) { super(); diff --git a/packages/grpc-js/src/server.ts b/packages/grpc-js/src/server.ts index d1859c39..018ec171 100644 --- a/packages/grpc-js/src/server.ts +++ b/packages/grpc-js/src/server.ts @@ -150,10 +150,6 @@ interface ChannelzSessionInfo { lastMessageReceivedTimestamp: Date | null; } -interface ChannelzListenerInfo { - ref: SocketRef; -} - export class Server { private http2ServerList: { server: http2.Http2Server | http2.Http2SecureServer; diff --git a/packages/grpc-js/src/subchannel-call.ts b/packages/grpc-js/src/subchannel-call.ts index 5d87fc80..e06ece38 100644 --- a/packages/grpc-js/src/subchannel-call.ts +++ b/packages/grpc-js/src/subchannel-call.ts @@ -23,8 +23,6 @@ import { Metadata } from './metadata'; import { StreamDecoder } from './stream-decoder'; import * as logging from './logging'; import { LogVerbosity } from './constants'; -import { ServerSurfaceCall } from './server-call'; -import { Deadline } from './deadline'; import { InterceptingListener, MessageContext, @@ -35,9 +33,6 @@ import { CallEventTracker, Transport } from './transport'; const TRACER_NAME = 'subchannel_call'; -const { HTTP2_HEADER_STATUS, HTTP2_HEADER_CONTENT_TYPE, NGHTTP2_CANCEL } = - http2.constants; - /** * https://nodejs.org/api/errors.html#errors_class_systemerror */ diff --git a/packages/grpc-js/src/transport.ts b/packages/grpc-js/src/transport.ts index bfdc1148..9d784cbd 100644 --- a/packages/grpc-js/src/transport.ts +++ b/packages/grpc-js/src/transport.ts @@ -67,10 +67,6 @@ const { HTTP2_HEADER_USER_AGENT, } = http2.constants; -/* setInterval and setTimeout only accept signed 32 bit integers. JS doesn't - * have a constant for the max signed 32 bit integer, so this is a simple way - * to calculate it */ -const KEEPALIVE_MAX_TIME_MS = ~(1 << 31); const KEEPALIVE_TIMEOUT_MS = 20000; export interface CallEventTracker { @@ -135,11 +131,6 @@ class Http2Transport implements Transport { // Channelz info private channelzRef: SocketRef; private readonly channelzEnabled: boolean = true; - /** - * Name of the remote server, if it is not the same as the subchannel - * address, i.e. if connecting through an HTTP CONNECT proxy. - */ - private remoteName: string | null = null; private streamTracker = new ChannelzCallTracker(); private keepalivesSent = 0; private messagesSent = 0; @@ -150,7 +141,12 @@ class Http2Transport implements Transport { constructor( private session: http2.ClientHttp2Session, subchannelAddress: SubchannelAddress, - options: ChannelOptions + options: ChannelOptions, + /** + * Name of the remote server, if it is not the same as the subchannel + * address, i.e. if connecting through an HTTP CONNECT proxy. + */ + private remoteName: string | null ) { // Build user-agent string. this.userAgent = [ @@ -584,7 +580,9 @@ export class Http2SubchannelConnector implements SubchannelConnector { private session: http2.ClientHttp2Session | null = null; private isShutdown = false; constructor(private channelTarget: GrpcUri) {} - private trace(text: string) {} + private trace(text: string) { + logging.trace(LogVerbosity.DEBUG, TRACER_NAME, this.channelTarget + ' ' + text); + } private createSession( address: SubchannelAddress, credentials: ChannelCredentials, @@ -702,7 +700,7 @@ export class Http2SubchannelConnector implements SubchannelConnector { session.unref(); session.once('connect', () => { session.removeAllListeners(); - resolve(new Http2Transport(session, address, options)); + resolve(new Http2Transport(session, address, options, remoteName)); this.session = null; }); session.once('close', () => { diff --git a/packages/grpc-js/test/test-channel-credentials.ts b/packages/grpc-js/test/test-channel-credentials.ts index d52bb59d..614c8951 100644 --- a/packages/grpc-js/test/test-channel-credentials.ts +++ b/packages/grpc-js/test/test-channel-credentials.ts @@ -19,17 +19,11 @@ import * as assert from 'assert'; import * as fs from 'fs'; import * as path from 'path'; import { promisify } from 'util'; -import * as protoLoader from '@grpc/proto-loader'; import { CallCredentials } from '../src/call-credentials'; import { ChannelCredentials } from '../src/channel-credentials'; import * as grpc from '../src'; import { ServiceClient, ServiceClientConstructor } from '../src/make-client'; -import { - TestServiceClient, - TestServiceHandlers, -} from './generated/TestService'; -import { ProtoGrpcType as TestServiceGrpcType } from './generated/test_service'; import { assert2, loadProtoFile, mockFunction } from './common'; import { sendUnaryData, ServerUnaryCall, ServiceError } from '../src'; @@ -179,18 +173,23 @@ describe('ChannelCredentials usage', () => { }, }); - server.bindAsync('localhost:0', serverCreds, (err, port) => { - if (err) { - reject(err); - return; + server.bindAsync( + 'localhost:0', + serverCreds, + (err, port) => { + if (err) { + reject(err); + return; + } + client = new echoService( + `localhost:${port}`, + combinedCreds, + {'grpc.ssl_target_name_override': 'foo.test.google.fr', 'grpc.default_authority': 'foo.test.google.fr'} + ); + server.start(); + resolve(); } - client = new echoService(`localhost:${port}`, combinedCreds, { - 'grpc.ssl_target_name_override': 'foo.test.google.fr', - 'grpc.default_authority': 'foo.test.google.fr', - }); - server.start(); - resolve(); - }); + ); }); }); after(() => { diff --git a/packages/grpc-js/test/test-channelz.ts b/packages/grpc-js/test/test-channelz.ts index 86c90b77..e740c432 100644 --- a/packages/grpc-js/test/test-channelz.ts +++ b/packages/grpc-js/test/test-channelz.ts @@ -21,8 +21,6 @@ import * as grpc from '../src'; import { ProtoGrpcType } from '../src/generated/channelz'; import { ChannelzClient } from '../src/generated/grpc/channelz/v1/Channelz'; -import { Channel__Output } from '../src/generated/grpc/channelz/v1/Channel'; -import { Server__Output } from '../src/generated/grpc/channelz/v1/Server'; import { ServiceClient, ServiceClientConstructor } from '../src/make-client'; import { loadProtoFile } from './common'; diff --git a/packages/grpc-js/test/test-deadline.ts b/packages/grpc-js/test/test-deadline.ts index 315f8b3c..9de3687c 100644 --- a/packages/grpc-js/test/test-deadline.ts +++ b/packages/grpc-js/test/test-deadline.ts @@ -19,14 +19,10 @@ import * as assert from 'assert'; import * as grpc from '../src'; import { experimental } from '../src'; -import { ServerCredentials } from '../src'; import { ServiceClient, ServiceClientConstructor } from '../src/make-client'; import { loadProtoFile } from './common'; import ServiceConfig = experimental.ServiceConfig; -const clientInsecureCreds = grpc.credentials.createInsecure(); -const serverInsecureCreds = ServerCredentials.createInsecure(); - const TIMEOUT_SERVICE_CONFIG: ServiceConfig = { loadBalancingConfig: [], methodConfig: [ diff --git a/packages/grpc-js/test/test-outlier-detection.ts b/packages/grpc-js/test/test-outlier-detection.ts index aa35f45e..a9629a56 100644 --- a/packages/grpc-js/test/test-outlier-detection.ts +++ b/packages/grpc-js/test/test-outlier-detection.ts @@ -19,8 +19,7 @@ import * as assert from 'assert'; import * as path from 'path'; import * as grpc from '../src'; import { loadProtoFile } from './common'; -import { OutlierDetectionLoadBalancingConfig } from '../src/load-balancer-outlier-detection'; -import { ServiceClient } from '../src/make-client'; +import { OutlierDetectionLoadBalancingConfig } from '../src/load-balancer-outlier-detection' function multiDone(done: Mocha.Done, target: number) { let count = 0; @@ -372,6 +371,16 @@ describe('Outlier detection config validation', () => { }, /failure_percentage_ejection\.enforcement_percentage parse error: value out of range for percentage/); }); }); + describe('child_policy', () => { + it('Should reject a pick_first child_policy', () => { + const loadBalancingConfig = { + child_policy: [{pick_first: {}}] + }; + assert.throws(() => { + OutlierDetectionLoadBalancingConfig.createFromJson(loadBalancingConfig); + }, /outlier_detection LB policy cannot have a pick_first child policy/); + }); + }); }); describe('Outlier detection', () => { diff --git a/packages/grpc-js/test/test-server.ts b/packages/grpc-js/test/test-server.ts index 7a0fb412..b0171244 100644 --- a/packages/grpc-js/test/test-server.ts +++ b/packages/grpc-js/test/test-server.ts @@ -717,7 +717,7 @@ describe('Compressed requests', () => { }, ServerStream(call) { - const { metadata, request } = call; + const { request } = call; for (let i = 0; i < 5; i++) { call.write({ count: request.message.length }); diff --git a/packages/grpc-js/tsconfig.json b/packages/grpc-js/tsconfig.json index d678782c..763ceda9 100644 --- a/packages/grpc-js/tsconfig.json +++ b/packages/grpc-js/tsconfig.json @@ -16,7 +16,8 @@ "module": "commonjs", "resolveJsonModule": true, "incremental": true, - "types": ["mocha"] + "types": ["mocha"], + "noUnusedLocals": true }, "include": [ "src/**/*.ts",