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

Client stream with unary response not returning response #105

Closed
seanhagen opened this issue Sep 7, 2018 · 6 comments
Closed

Client stream with unary response not returning response #105

seanhagen opened this issue Sep 7, 2018 · 6 comments

Comments

@seanhagen
Copy link

In the latest version, streaming has been enabled -- which is awesome.

In testing this out against an example service, we're able to get two of the three types of streaming working:

syntax = "proto3";
package api;

service Ping {
  rpc PingMe(PingMessage) returns (PongMessage) {} //works
  rpc StreamIn(stream PingMessage) returns (PingCountMessage) {}// doesn't work!
  rpc StreamBack(PingCountMessage) returns (stream PingMessage) {} //works
  rpc StreamPing(stream PingMessage) returns (stream PongMessage) {}//works
}

message PingMessage {
  string greeting = 1;
}

message PongMessage {
  string response = 1;
}

message PingCountMessage {
  int64 count = 1;
  string message = 2;
}

message StreamPingMessage {
  int64 count = 1;
  string msg  = 2;
}

The problem is that while the server gets all the messages sent by the client when StreamIn is called, the client doesn't receive the response when it's indicated that its's finished sending.

Looking at other languages, when doing client streaming they usually have a method CloseAndRecv(), which lets the server know the client is done streaming and it can do what it needs to do before sending the response (and/or error).

When using the grpc-web Websocket transport or a hacked default transport* then the server receives the messages sent by the client, but the client doesn't receive the final message/error from the server when finishSend is called.

* hacking Transport.ts to remove the following (because fetch/websockets now allow request streaming):

  if (transportOptions.methodDefinition.requestStream) {
    return new Error("No transport available for client-streaming (requestStream) method");
  }
@jonnyreeves
Copy link
Contributor

Hi @seanhagen, thanks for trying out the new ClientStream and BiDiStream code generation, let's try and get this working :)

Looking at other languages, when doing client streaming they usually have a method CloseAndRecv(), which lets the server know the client is done streaming and it can do what it needs to do before sending the response (and/or error).

Without seeing your code which invokes the client and sends the data I'm going to take a wild stab in the dark and check that you are invoking RequestStream#end()?

If you are invoking end() then posting up a repro of the issue would really help me debug this further if you are unable to.

Thanks!

@jonny-improbable
Copy link
Contributor

Hi @seanhagen were you able to provide a repro for this issue? Thanks!

@seanhagen
Copy link
Author

Okay, things have been busy here but finally got a repro repo up: https://github.com/Z2hMedia/client-stream-repro

The backend we used to test is in go, here's a gist for how the methods are implemented: https://gist.github.com/seanhagen/49634abdaa3ddd5da1953948e01f8a37

@stale
Copy link

stale bot commented Jan 20, 2019

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the wontfix label Jan 20, 2019
@stale stale bot closed this as completed Jan 28, 2019
@asutula
Copy link

asutula commented May 22, 2020

Would love to see this issue reopened. The repo @seanhagen links to above illustrates the problem perfectly. Because of this behavior, I've resorted to using the general grpc.client to execute client streaming requests... not ideal.

@asutula
Copy link

asutula commented May 22, 2020

Just to point this out, the generated code for a client side stream looks like:

interface RequestStream<T> {
  write(message: T): RequestStream<T>;
  end(): void;
  cancel(): void;
  on(type: 'end', handler: (status?: Status) => void): RequestStream<T>;
  on(type: 'status', handler: (status: Status) => void): RequestStream<T>;
}

There seems to be no way to get the final response from the server.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants