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

How to cancel a GRPC Server streaming call #3095

Closed
varshanbp opened this issue Jun 13, 2017 · 13 comments
Closed

How to cancel a GRPC Server streaming call #3095

varshanbp opened this issue Jun 13, 2017 · 13 comments

Comments

@varshanbp
Copy link

I made a Call to server. The server streams. I want to cancel the call from client.

How to cancel? No Method to cancel a call.

@fanminshi
Copy link

@varshanbp I think you need to call onCompleted() of the streamObserver from client to terminate the stream call.
http://www.grpc.io/docs/tutorials/basic/java.html

@varshanbp
Copy link
Author

varshanbp commented Jun 15, 2017

@fanminshi I use "Server-side streaming RPC". I want to close the channel from client. If I shutdown channel from client, it throws error in Server and keeps returning value to closed channel. How to solve this problem?

I want to close a channel from Client properly.

@conorgriffin
Copy link

@varshanbp wants to shut down the stream from the client side, this example shuts it down from the server side @fanminshi

@fanminshi
Copy link

fanminshi commented Jun 16, 2017

@conorgriffin oops. wrong example. I meant to show this one.

you probably don't want to kill channel right away. maybe follow the example here to properly shutdown channel.

  public void shutdown() throws InterruptedException {
    channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
  }

https://github.com/grpc/grpc-java/blob/master/examples/src/main/java/io/grpc/examples/routeguide/RouteGuideClient.java#L62-L64

@carl-mastrangelo
Copy link
Contributor

@varshanbp In the future, this kind of question would be better posted on Stack Overflow or the mailing list.

To answer your question: You can cancel a call on the client by calling onError(Status.CANCELED). The actual error doesn't matter too much since it won't actually be put on the wire. gRPC will send an RST_STREAM packet which will show up on the server's onError handler.

If you want a more graceful shutdown, you can modify your streaming RPC to just make onCompleted interpreted as a cancellation, which will make things close down more gracefully.

Note that ManagedChannel.shutdown won't end any in progress RPCs. It just says that no new RPCs can be started, and that once the number of active RPCs is 0, the channel will close all connections. If you want a more active shutdown, you can use shutdownNow, which cancels all streams too.

@ejona86
Copy link
Member

ejona86 commented Jun 19, 2017

@carl-mastrangelo, the client can't call onError(Status) on server-streaming calls, since it doesn't have a request StreamObserver. Today, the only way to cancel the call is by cancelling the Context. So you'd need to create a CancellableContext before the call and cancel it when necessary or when the call is complete.

It'd be a good API to add to ClientCallStreamObserver.

@dapengzhang0
Copy link
Member

@ejona86 another way to cancel server-streaming calls or unary calls from client side is using an interceptor, and call ClientCall.cancel

@JanecekPetr
Copy link

We've been trying to find a solution for canceling unary calls a few months ago. We found that unary calls are uncancelable by design ("unary calls should provide enough information to the server to make the server cancel properly" - sorry, can't find the quote now as I'm on mobile, but it comes from grpc devs).

Since then we've been marking all our cancelable unary calls as streaming (while documenting the intent).

@ejona86
Copy link
Member

ejona86 commented Jul 25, 2017

We found that unary calls are uncancelable by design

No, they should be cancellable. It is important that they can be cancelled on-demand by the client. That is non-negotiable (it's been argued before), so if you'd like me to argue with another dev I can :)

Since then we've been marking all our cancelable unary calls as streaming (while documenting the intent).

Yeah, that doesn't really help anyone. Unary RPCs are much easier to use in most languages.

@JanecekPetr
Copy link

JanecekPetr commented Jul 26, 2017

Yeah, you're right, sorry. I found the quote: grpc/grpc#8023 (comment). Apparently I misread that / misremember that.

In general, the assumption of a server-only streaming call is that the initial message from the client contains enough information for the server to know when to stop.

If the client unexpectedly has to stop the stream in the middle, you can cancel the call (call.cancel()). Note that this will terminate the call with a CANCELLED status.

which basically says what you're saying. And yet at the time of testing this (in February) we did not find a working solution in Java/node.js. I'll try again with the context stuff you mentioned. Still this sucks more than it should.

Thanks for clearing this up, it actually makes gRPC looks good to me again. We wrote a whole machinery around these cancallable server-streaming calls, and I'm looking forward to deleting it all.

(EDIT: Removed some wrong assumptions. I don't remember things correctly after 5 months of not working with this anymore.)

@ejona86
Copy link
Member

ejona86 commented Jul 26, 2017

I'll try again with the context stuff you mentioned. Still this sucks more than it should.

Agreed. But on the bright side #3115 is merged and will be available in 1.6. Also, using ClientCall directly isn't that bad and isn't too different than the StreamObserver, so that's another short-term option.

It's in the Context documentation, but when making your own CancellableContext, make sure you cancel it when done with it (in the success case).

@jzillmann
Copy link

Am i right, that there is no way to cancel using the auto-generated stubs (Java) !?
I would have to stop using the stubs and invoke getChannel().newCall by myself ?

@ejona86
Copy link
Member

ejona86 commented Oct 23, 2017

@jzillmann you can use io.grpc.Context to cancel any stub type. For blocking you can interrupt the thread; for future you can cancel the future; for async you can use ClientCallStreamObserver.cancel() by casting the returned StreamObserver to ClientCallStreamObserver or implementing having your passed-in StreamObserver implement ClientResponseObserver.

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

No branches or pull requests

8 participants