Skip to content
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

grpc-js: Improve event sequencing when handling connection drops #2862

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/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@grpc/grpc-js",
"version": "1.12.3",
"version": "1.12.4",
"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
27 changes: 21 additions & 6 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 @@ -240,8 +242,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 +331,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
12 changes: 4 additions & 8 deletions packages/grpc-js/src/transport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -387,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