Skip to content

Merge grpc-js 1.12.x into master #2877

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Jan 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/grpc-js-xds/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"@types/gulp": "^4.0.6",
"@types/gulp-mocha": "0.0.32",
"@types/mocha": "^5.2.6",
"@types/node": "^13.11.1",
"@types/node": ">=20.11.20",
"@types/yargs": "^15.0.5",
"find-free-ports": "^3.1.1",
"gts": "^5.0.1",
Expand Down
4 changes: 2 additions & 2 deletions packages/grpc-js-xds/src/load-balancer-priority.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,8 @@ export class PriorityLoadBalancer implements LoadBalancer {
private connectivityState: ConnectivityState = ConnectivityState.IDLE;
private picker: Picker;
private childBalancer: ChildLoadBalancerHandler;
private failoverTimer: NodeJS.Timer | null = null;
private deactivationTimer: NodeJS.Timer | null = null;
private failoverTimer: NodeJS.Timeout | null = null;
private deactivationTimer: NodeJS.Timeout | null = null;
private seenReadyOrIdleSinceTransientFailure = false;
constructor(private parent: PriorityLoadBalancer, private name: string, ignoreReresolutionRequests: boolean) {
this.childBalancer = new ChildLoadBalancerHandler(experimental.createChildChannelControlHelper(this.parent.channelControlHelper, {
Expand Down
2 changes: 1 addition & 1 deletion packages/grpc-js-xds/src/load-balancer-weighted-target.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ export class WeightedTargetLoadBalancer implements LoadBalancer {
private connectivityState: ConnectivityState = ConnectivityState.IDLE;
private picker: Picker;
private childBalancer: ChildLoadBalancerHandler;
private deactivationTimer: NodeJS.Timer | null = null;
private deactivationTimer: NodeJS.Timeout | null = null;
private weight: number = 0;

constructor(private parent: WeightedTargetLoadBalancer, private name: string) {
Expand Down
10 changes: 5 additions & 5 deletions packages/grpc-js-xds/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,7 @@ interface MatchFieldEvaluator<MatcherType, FieldType> {
isMoreSpecific: (matcher1: MatcherType, matcher2: MatcherType) => boolean;
}

type FieldType<MatcherType> = MatcherType extends CidrRange ? (string | undefined) : MatcherType extends (ConnectionSourceType) ? {localAddress: string, remoteAddress?: (string | undefined)} : MatcherType extends number ? number | undefined : never;
type FieldType<MatcherType> = MatcherType extends CidrRange ? (string | undefined) : MatcherType extends (ConnectionSourceType) ? {localAddress?: (string | undefined), remoteAddress?: (string | undefined)} : MatcherType extends number ? number | undefined : never;

function cidrRangeMatch(range: CidrRange | undefined, address: string | undefined): boolean {
return !range || (!!address && inCidrRange(range, address));
Expand All @@ -473,14 +473,14 @@ function cidrRangeMoreSpecific(range1: CidrRange | undefined, range2: CidrRange
return !!range1 && range1.prefixLen > range2.prefixLen;
}

function sourceTypeMatch(sourceType: ConnectionSourceType, addresses: {localAddress: string, remoteAddress?: (string | undefined)}): boolean {
function sourceTypeMatch(sourceType: ConnectionSourceType, addresses: {localAddress?: (string | undefined), remoteAddress?: (string | undefined)}): boolean {
switch (sourceType) {
case "ANY":
return true;
case "SAME_IP_OR_LOOPBACK":
return !!addresses.remoteAddress && isSameIpOrLoopback(addresses.remoteAddress, addresses.localAddress);
return !!addresses.localAddress && !!addresses.remoteAddress && isSameIpOrLoopback(addresses.remoteAddress, addresses.localAddress);
case "EXTERNAL":
return !!addresses.remoteAddress && !isSameIpOrLoopback(addresses.remoteAddress, addresses.localAddress);
return !!addresses.localAddress && !!addresses.remoteAddress && !isSameIpOrLoopback(addresses.remoteAddress, addresses.localAddress);
}
}

Expand All @@ -490,7 +490,7 @@ const cidrRangeEvaluator: MatchFieldEvaluator<CidrRange | undefined, string | un
isMoreSpecific: cidrRangeMoreSpecific
};

const sourceTypeEvaluator: MatchFieldEvaluator<ConnectionSourceType, {localAddress: string, remoteAddress?: (string | undefined)}> = {
const sourceTypeEvaluator: MatchFieldEvaluator<ConnectionSourceType, {localAddress?: (string | undefined), remoteAddress?: (string | undefined)}> = {
isMatch: sourceTypeMatch,
matcherEqual: (matcher1, matcher2) => matcher1 === matcher2,
isMoreSpecific: (matcher1, matcher2) => matcher1 !== 'ANY' && matcher2 === 'ANY'
Expand Down
4 changes: 2 additions & 2 deletions packages/grpc-js-xds/src/xds-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ export class Watcher<UpdateType> implements ResourceWatcherInterface {
const RESOURCE_TIMEOUT_MS = 15_000;

class ResourceTimer {
private timer: NodeJS.Timer | null = null;
private timer: NodeJS.Timeout | null = null;
private resourceSeen = false;
constructor(private callState: AdsCallState, private type: XdsResourceType, private name: XdsResourceName) {}

Expand Down Expand Up @@ -672,7 +672,7 @@ class ClusterLoadReportMap {
}

class LrsCallState {
private statsTimer: NodeJS.Timer | null = null;
private statsTimer: NodeJS.Timeout | null = null;
private sentInitialMessage = false;
constructor(private client: XdsSingleServerClient, private call: LrsCall, private node: Node) {
call.on('data', (message: LoadStatsResponse__Output) => {
Expand Down
2 changes: 1 addition & 1 deletion packages/grpc-js-xds/test/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const BOOTSTRAP_CONFIG_KEY = 'grpc.TEST_ONLY_DO_NOT_USE_IN_PROD.xds_bootstrap_co

export class XdsTestClient {
private client: EchoTestServiceClient;
private callInterval: NodeJS.Timer;
private callInterval: NodeJS.Timeout;

constructor(target: string, bootstrapInfo: string, options?: ChannelOptions) {
this.client = new loadedProtos.grpc.testing.EchoTestService(target, credentials.createInsecure(), {...options, [BOOTSTRAP_CONFIG_KEY]: bootstrapInfo});
Expand Down
2 changes: 1 addition & 1 deletion packages/grpc-js/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@grpc/grpc-js",
"version": "1.12.1",
"version": "1.12.5",
"description": "gRPC Library for Node - pure JS implementation",
"homepage": "https://grpc.io/",
"repository": "https://github.com/grpc/grpc-node/tree/master/packages/grpc-js",
Expand Down
11 changes: 7 additions & 4 deletions packages/grpc-js/src/certificate-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@
*
*/

import * as fs from 'fs/promises';
import * as fs from 'fs';
import * as logging from './logging';
import { LogVerbosity } from './constants';
import { promisify } from 'util';

const TRACER_NAME = 'certificate_provider';

Expand Down Expand Up @@ -56,6 +57,8 @@ export interface FileWatcherCertificateProviderConfig {
refreshIntervalMs: number;
}

const readFilePromise = promisify(fs.readFile);

export class FileWatcherCertificateProvider implements CertificateProvider {
private refreshTimer: NodeJS.Timeout | null = null;
private fileResultPromise: Promise<[PromiseSettledResult<Buffer>, PromiseSettledResult<Buffer>, PromiseSettledResult<Buffer>]> | null = null;
Expand All @@ -82,9 +85,9 @@ export class FileWatcherCertificateProvider implements CertificateProvider {
return;
}
this.fileResultPromise = Promise.allSettled([
this.config.certificateFile ? fs.readFile(this.config.certificateFile) : Promise.reject<Buffer>(),
this.config.privateKeyFile ? fs.readFile(this.config.privateKeyFile) : Promise.reject<Buffer>(),
this.config.caCertificateFile ? fs.readFile(this.config.caCertificateFile) : Promise.reject<Buffer>()
this.config.certificateFile ? readFilePromise(this.config.certificateFile) : Promise.reject<Buffer>(),
this.config.privateKeyFile ? readFilePromise(this.config.privateKeyFile) : Promise.reject<Buffer>(),
this.config.caCertificateFile ? readFilePromise(this.config.caCertificateFile) : Promise.reject<Buffer>()
]);
this.fileResultPromise.then(([certificateResult, privateKeyResult, caCertificateResult]) => {
if (!this.refreshTimer) {
Expand Down
44 changes: 37 additions & 7 deletions packages/grpc-js/src/subchannel-call.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ export class Http2SubchannelCall implements SubchannelCall {

private serverEndedCall = false;

private connectionDropped = false;

constructor(
private readonly http2Stream: http2.ClientHttp2Stream,
private readonly callEventTracker: CallEventTracker,
Expand Down Expand Up @@ -188,7 +190,22 @@ export class Http2SubchannelCall implements SubchannelCall {
try {
messages = this.decoder.write(data);
} catch (e) {
this.cancelWithStatus(Status.RESOURCE_EXHAUSTED, (e as Error).message);
/* Some servers send HTML error pages along with HTTP status codes.
* When the client attempts to parse this as a length-delimited
* message, the parsed message size is greater than the default limit,
* resulting in a message decoding error. In that situation, the HTTP
* error code information is more useful to the user than the
* RESOURCE_EXHAUSTED error is, so we report that instead. Normally,
* we delay processing the HTTP status until after the stream ends, to
* prioritize reporting the gRPC status from trailers if it is present,
* but when there is a message parsing error we end the stream early
* before processing trailers. */
if (this.httpStatusCode !== undefined && this.httpStatusCode !== 200) {
const mappedStatus = mapHttpStatusCode(this.httpStatusCode);
this.cancelWithStatus(mappedStatus.code, mappedStatus.details);
} else {
this.cancelWithStatus(Status.RESOURCE_EXHAUSTED, (e as Error).message);
}
return;
}

Expand Down Expand Up @@ -240,8 +257,16 @@ export class Http2SubchannelCall implements SubchannelCall {
details = 'Stream refused by server';
break;
case http2.constants.NGHTTP2_CANCEL:
code = Status.CANCELLED;
details = 'Call cancelled';
/* Bug reports indicate that Node synthesizes a NGHTTP2_CANCEL
* code from connection drops. We want to prioritize reporting
* an unavailable status when that happens. */
if (this.connectionDropped) {
code = Status.UNAVAILABLE;
details = 'Connection dropped';
} else {
code = Status.CANCELLED;
details = 'Call cancelled';
}
break;
case http2.constants.NGHTTP2_ENHANCE_YOUR_CALM:
code = Status.RESOURCE_EXHAUSTED;
Expand Down Expand Up @@ -321,10 +346,15 @@ export class Http2SubchannelCall implements SubchannelCall {
}

public onDisconnect() {
this.endCall({
code: Status.UNAVAILABLE,
details: 'Connection dropped',
metadata: new Metadata(),
this.connectionDropped = true;
/* Give the call an event loop cycle to finish naturally before reporting
* the disconnection as an error. */
setImmediate(() => {
this.endCall({
code: Status.UNAVAILABLE,
details: 'Connection dropped',
metadata: new Metadata(),
});
});
}

Expand Down
17 changes: 9 additions & 8 deletions packages/grpc-js/src/transport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,11 @@ class Http2Transport implements Transport {
this.handleDisconnect();
});

session.socket.once('close', () => {
this.trace('connection closed');
this.handleDisconnect();
});

if (logging.isTracerEnabled(TRACER_NAME)) {
session.on('remoteSettings', (settings: http2.Settings) => {
this.trace(
Expand Down Expand Up @@ -382,17 +387,13 @@ class Http2Transport implements Transport {
* Handle connection drops, but not GOAWAYs.
*/
private handleDisconnect() {
if (this.disconnectHandled) {
return;
}
this.clearKeepaliveTimeout();
this.reportDisconnectToOwner(false);
/* Give calls an event loop cycle to finish naturally before reporting the
* disconnnection to them. */
for (const call of this.activeCalls) {
call.onDisconnect();
}
// Wait an event loop cycle before destroying the connection
setImmediate(() => {
for (const call of this.activeCalls) {
call.onDisconnect();
}
this.session.destroy();
});
}
Expand Down
28 changes: 15 additions & 13 deletions packages/grpc-js/test/fixtures/ca.pem
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
-----BEGIN CERTIFICATE-----
MIICSjCCAbOgAwIBAgIJAJHGGR4dGioHMA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQxDzANBgNVBAMTBnRlc3RjYTAeFw0xNDExMTEyMjMxMjla
Fw0yNDExMDgyMjMxMjlaMFYxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0
YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxDzANBgNVBAMT
BnRlc3RjYTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwEDfBV5MYdlHVHJ7
+L4nxrZy7mBfAVXpOc5vMYztssUI7mL2/iYujiIXM+weZYNTEpLdjyJdu7R5gGUu
g1jSVK/EPHfc74O7AyZU34PNIP4Sh33N+/A5YexrNgJlPY+E3GdVYi4ldWJjgkAd
Qah2PH5ACLrIIC6tRka9hcaBlIECAwEAAaMgMB4wDAYDVR0TBAUwAwEB/zAOBgNV
HQ8BAf8EBAMCAgQwDQYJKoZIhvcNAQELBQADgYEAHzC7jdYlzAVmddi/gdAeKPau
sPBG/C2HCWqHzpCUHcKuvMzDVkY/MP2o6JIW2DBbY64bO/FceExhjcykgaYtCH/m
oIU63+CFOTtR7otyQAWHqXa7q4SbCDlG7DyRFxqG0txPtGvy12lgldA2+RgcigQG
Dfcog5wrJytaQ6UA0wE=
MIICzDCCAjWgAwIBAgIBBzANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQGEwJVUzER
MA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xFTATBgNVBAoTDEV4
YW1wbGUsIENvLjEaMBgGA1UEAxQRKi50ZXN0Lmdvb2dsZS5jb20wHhcNMjQxMTE0
MDEzMjM3WhcNNDQxMTA5MDEzMjM3WjBlMQswCQYDVQQGEwJVUzERMA8GA1UECBMI
SWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xFTATBgNVBAoTDEV4YW1wbGUsIENv
LjEaMBgGA1UEAxQRKi50ZXN0Lmdvb2dsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQAD
gY0AMIGJAoGBAOHDFScoLCVJpYDDM4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlu
mN+fm+AjPEK5GHhGn1BgzkWF+slf3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wH
NVX77fBZOgp9VlSMVfyd9N8YwbBYAckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAGj
gYswgYgwCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAwTwYDVR0RBEgwRoIQKi50ZXN0
Lmdvb2dsZS5mcoIYd2F0ZXJ6b29pLnRlc3QuZ29vZ2xlLmJlghIqLnRlc3QueW91
dHViZS5jb22HBMCoAQMwHQYDVR0OBBYEFI50QV/hcKkD2qyS/Melvq16+zY8MA0G
CSqGSIb3DQEBCwUAA4GBAIxvZ4kg9HAvzM31p4J04h1MFfnDx8O4Hwogzpaqk+0M
qz8L1ojJy5jus1g8+RBguT1rv5TmRFpMWrp50XQ0bMFHoOcNyL0htxoOhmoKHoX9
dM0KWtgUheeBcEm83UzFFlGKlna22+pdUHLEnuX+i25s+Lbi4/LGf6KwUlgPL/Vk
-----END CERTIFICATE-----
29 changes: 15 additions & 14 deletions packages/grpc-js/test/fixtures/server1.pem
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
-----BEGIN CERTIFICATE-----
MIICnDCCAgWgAwIBAgIBBzANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJBVTET
MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ
dHkgTHRkMQ8wDQYDVQQDEwZ0ZXN0Y2EwHhcNMTUxMTA0MDIyMDI0WhcNMjUxMTAx
MDIyMDI0WjBlMQswCQYDVQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNV
BAcTB0NoaWNhZ28xFTATBgNVBAoTDEV4YW1wbGUsIENvLjEaMBgGA1UEAxQRKi50
ZXN0Lmdvb2dsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOHDFSco
LCVJpYDDM4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlumN+fm+AjPEK5GHhGn1Bg
zkWF+slf3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wHNVX77fBZOgp9VlSMVfyd
9N8YwbBYAckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAGjazBpMAkGA1UdEwQCMAAw
CwYDVR0PBAQDAgXgME8GA1UdEQRIMEaCECoudGVzdC5nb29nbGUuZnKCGHdhdGVy
em9vaS50ZXN0Lmdvb2dsZS5iZYISKi50ZXN0LnlvdXR1YmUuY29thwTAqAEDMA0G
CSqGSIb3DQEBCwUAA4GBAJFXVifQNub1LUP4JlnX5lXNlo8FxZ2a12AFQs+bzoJ6
hM044EDjqyxUqSbVePK0ni3w1fHQB5rY9yYC5f8G7aqqTY1QOhoUk8ZTSTRpnkTh
y4jjdvTZeLDVBlueZUTDRmy2feY5aZIU18vFDK08dTG0A87pppuv1LNIR3loveU8
MIICzDCCAjWgAwIBAgIBBzANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQGEwJVUzER
MA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xFTATBgNVBAoTDEV4
YW1wbGUsIENvLjEaMBgGA1UEAxQRKi50ZXN0Lmdvb2dsZS5jb20wHhcNMjQxMTE0
MDEzMjM3WhcNNDQxMTA5MDEzMjM3WjBlMQswCQYDVQQGEwJVUzERMA8GA1UECBMI
SWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xFTATBgNVBAoTDEV4YW1wbGUsIENv
LjEaMBgGA1UEAxQRKi50ZXN0Lmdvb2dsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQAD
gY0AMIGJAoGBAOHDFScoLCVJpYDDM4HYtIdV6Ake/sMNaaKdODjDMsux/4tDydlu
mN+fm+AjPEK5GHhGn1BgzkWF+slf3BxhrA/8dNsnunstVA7ZBgA/5qQxMfGAq4wH
NVX77fBZOgp9VlSMVfyd9N8YwbBYAckOeUQadTi2X1S6OgJXgQ0m3MWhAgMBAAGj
gYswgYgwCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAwTwYDVR0RBEgwRoIQKi50ZXN0
Lmdvb2dsZS5mcoIYd2F0ZXJ6b29pLnRlc3QuZ29vZ2xlLmJlghIqLnRlc3QueW91
dHViZS5jb22HBMCoAQMwHQYDVR0OBBYEFI50QV/hcKkD2qyS/Melvq16+zY8MA0G
CSqGSIb3DQEBCwUAA4GBAIxvZ4kg9HAvzM31p4J04h1MFfnDx8O4Hwogzpaqk+0M
qz8L1ojJy5jus1g8+RBguT1rv5TmRFpMWrp50XQ0bMFHoOcNyL0htxoOhmoKHoX9
dM0KWtgUheeBcEm83UzFFlGKlna22+pdUHLEnuX+i25s+Lbi4/LGf6KwUlgPL/Vk
-----END CERTIFICATE-----
Loading