question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

add a flag to ServerCallStreamObserver to make onCompleted() throw StatusRuntimeException if the call was cancelled

See original GitHub issue

Is your feature request related to a problem?

It is currently a bit cumbersome If a gRPC method needs to attempt to roll back effects of a call when the client cancels and work is not dispatched to other threads:

  • responseObserver.onNext(...) will not throw an exception neither in unary methods (they don’t throw on cancel by design) nor in server-streaming (due to issue #8409 ). Furthermore responseObserver.onNext() may never be called by some server-streaming methods that return a stream of length 0 but need to attempt to roll back side-effects of processing client’s request nevertheless.
  • onCancelHandler cannot be used as it will be called only after the method exits, due to listener’s “called by at most 1 thread at a time” contract.

Describe the solution you’d like

draft: https://github.com/morgwai/grpc-java/commit/f26b7db916f2cf5c08f4d0161586ad78ba998d6a If the general idea of this feature request is accepted, I will be happy to prepare a proper PR myself starting from the above draft.

Describe alternatives you’ve considered

Currently in cases like this, the easiest solution is to keep checking responseObserver.isCancelled() before responseObserver.onCompleted() (and in case of server-streaming calls possibly additionally before each responseObserver.onNext() if it’s desirable to interrupt processing ASAP). This however is kinda C-style: client cancelling is an exceptional situation, so I think it’s cleaner to handle it in a catch block rather and keep the main positive code-path clean.

Context.addListener() can probably be also used, but as the listener will be called by another thread, it will have to set a specially designated volatile/synchronized flag, which the code of the main positive case will need to examine before responseObserver.onCompleted(). Therefore it’s not better than the above solution using responseObserver.isCancelled().

Additional context

Even for methods that do dispatch work to other threads, using exception rather than onCancelHandler is a cleaner solution in some cases: as cancellation may occur in the middle of a call, onCancelHandler similarly as a listener set by Context.addListener() described above, often needs to set a specially designated volatile/synchronized flag to stop further processing, that again needs to be checked by the code of the main positive case, while an exception interrupts the main positive code-path with much less hassle.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:8 (8 by maintainers)

github_iconTop GitHub Comments

1reaction
ejona86commented, Aug 23, 2021

Okay. In that case then the onCancelHandler is your best bet. It is the most reliable notification of cancellation. And again, cancellation can occur after the server calls onCompleted(). If you are waiting to commit the transaction locally when onCompleted() is called, then #5895 would be a better approach. You’d prepare the transaction within the service handler and call streamObserver.onComplete(). If onCancelHandler fires, cancel the transaction. If (TBD) onCompleteHandler fires, commit the transaction.

Wanting an exception when calling onCompleted() is just broken, and has nothing to do with “c-style” or not. Async APIs generally don’t throw, because they’ve not done the operation yet! Normal Java practice for an async API (e.g., one that returns a Future) is to not throw and instead notify of the failure asynchronously (like failing the Future).

0reactions
ejona86commented, Aug 25, 2021

I sent out #8449 to document “things are async and can take a while.” I didn’t call out this specific detail about onCompleted(). That can be done as part of #5895.

Read more comments on GitHub >

github_iconTop Results From Across the Web

java: client cancels, but StatusRuntimeException not thrown ...
isCancelled() returns true but StatusRuntimeException is not thrown when calling onNext(...) and onCompleted() and call finishes as normal: server started.
Read more >
Can someone explain to me what's the proper usage of gRPC ...
Basically how do I properly use onError() and what should I expect and handle if I call it? I need an explanation of...
Read more >
Diff - platform/platform_testing - Google Git
menuOptions); /** - * Setup expectations: settings app is open and settings menu is selected - * - * Checks if the toggle...
Read more >
io.grpc:grpc-auth: Versions - Openbase
The error was in the form StatusRuntimeException: INTERNAL: http2 exception with a cause similar to Http2Exception$StreamException: Cannot create stream ...
Read more >
gRPC - 开源搜索- OSCHINA - 中文开源技术交流社区
所谓RPC(remote procedure call 远程过程调用)框架实际是提供了一套机制,使得应用程序之间可以进行通信,而且也遵从server/client模型。使用的时候客户端调用server端 ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found