Hello,
I'm trying to explore client back pressure for a unary server-streaming grpc call, implemented in Scala using grpc-java.
In my test, the server rpc call body loops 10 times, calling onNext(...) and sleeping for 1 second each time. To detect cancellation, I've registered a listener with the return from Context.current(), registered another handler using .setOnCancelHandler (after downcasting to ServerCallStreamObserver), and checked the value of serverCallStreamObserver.isCancelled.
The idea is that the server dribbles out 10 messages over (almost) 10 seconds, but should stop if a client cancels or drops out at any point. In my tests, I've had the client invoke the cancellation function immediately after receiving the first message, and have also manually quit the client program with Ctrl-C.Regardless, the server behaves the same: the loop executes 10 times (evidence via log messages), and during the call to streamObserver.onCompleted(), the cancellation listener fires. The OnCancelHandler seems to fire after the unary call itself returns (scope of the bound RPC handler exits). The .isCancelled function always returns false.
Now this is surprising to me. I thought that the point of these listeners and handlers (and the .isCancelled method) was so that the server could save resources by detecting when a client no longer cared about results. It doesn't seem to be working.
Do I need to wait for
https://github.com/grpc/grpc-java/issues/339 and implement on top of that, or do I need to do the "verbose and annoying" thing described in that PR? I would hate to go through the trouble of the "verbose and annoying" to find that it's broken in exactly the same way the OnCancelHandler and CancellationListener mechanics seem broken for me now.
Or is this some unfortunate consequence of the Scala runtime and some assumptions of immutability?
I would love to understand this better to know what code I need to write. Thanks to any kind souls who have time to enlighten me.
-Daniel