denoland / deno

A modern runtime for JavaScript and TypeScript.
https://deno.com
MIT License
93.4k stars 5.18k forks source link

gRPC connection fails #24305

Open garethj2 opened 2 weeks ago

garethj2 commented 2 weeks ago

Version: Deno 1.44.4

Client @grpc/grpc-js: 1.10.9 @grpc/grpc-proto-loader: 0.7.13

Server C++ gRPC version 1.51.1#3

I've been testing out the client of @grpc/grpc-js with Deno. In my code, I create a stream and listen for some events. After a period of time, I don't receive any more events and no more rpc calls seem to work.

Please note, I've run the exact same code using NodeJS and there appears to be no problem.

I've enabled logging in@grpc/grpc-js to help diagnose the issue. Here's a code snippet from @grpc/grpc-js where everything stops. Please see here for more details...

http2Stream.on('data', (data: Buffer) => {
      /* If the status has already been output, allow the http2 stream to
       * drain without processing the data. */
      if (this.statusOutput) {
        return;
      }
      this.trace('receive HTTP/2 data frame of length ' + data.length);
      const messages = this.decoder.write(data);

      for (const message of messages) {
        this.trace('parsed message of length ' + message.length);
        this.callEventTracker!.addMessageReceived();
        this.tryPush(message);
      }
    });

When everything stops working, the last trace I get is from receive HTTP/2 data frame of length. The passed message of length line is never reached.

Please note, I don't get any other errors. I have been monitoring the connection state using the recommended callbacks and I get nothing. It's almost like something goes fundamentally wrong with either the HTTP/2 connection or the Buffer being used to hold any received data.

Interestingly, the more events I ask for in my data stream, the quicker this problem occurs. With my default set up (i.e. 8 events), it takes about 100 seconds for the problem to occur. Here's an example of the type of data I receive in a response when everything does work...

{
  messageSequence: 217,
  messageTime: {
    seconds: Long { low: 1718966537, high: 0, unsigned: false },
    nanos: 250878378
  },
  valuesByUuid: {
    valueDict: {
      "07aa0319-0bc9-5cc4-9d7f-5400429c2ad9": {
        scalarInteger: { value: 39403 },
        qualityInfo: { qualityCode: 192 },
        stateChange: true,
        lastUpdated: { seconds: [Long], nanos: 247683500 }
      },
      "2fe11ba6-b713-53d1-85bf-17ccf6e261bd": {
        scalarFloat: { value: -0.9958083033561707 },
        qualityInfo: { qualityCode: 192 },
        stateChange: true,
        lastUpdated: { seconds: [Long], nanos: 247683500 }
      },
      "6d70fec2-728c-58f2-9b61-1dd2597ecc1b": {
        scalarInteger: { value: -1699249701 },
        qualityInfo: { qualityCode: 192 },
        stateChange: true,
        lastUpdated: { seconds: [Long], nanos: 247683500 }
      },
      "43b4e557-e717-5756-ac2b-42150aa851f7": {
        scalarInteger: { value: 39431 },
        qualityInfo: { qualityCode: 192 },
        stateChange: true,
        lastUpdated: { seconds: [Long], nanos: 247683500 }
      }
    }
  }
}

I've tried changing some of the default buffer sizes when opening the client connection. Nothing seems to make any difference. BTW when I set a keep alive message, I get a completely different broken pipe error but that's a completely different issue.

Hopefully this is enough information to track down whatever the issue may be.

satyarohith commented 1 week ago

@garethj2, thanks for opening the issue! I appreciate if you can provide a reproducible. It will fast track the process to fix the bug.

garethj2 commented 1 week ago

As requested, I've created a reproducible test case that reproduces the issue...

https://github.com/garethj2/deno-grpc-bug