feat(jsonrpc): add JsonRpcRequestFuture with explicit protocol cancel#907
Conversation
|
Thank you for this PR! 👍 I quite like the design in general, but I'd assume that calling |
Return a `JsonRpcRequestFuture` from `RemoteEndpoint.request(...)`, enabling `cancelRequest(boolean)` to send `$/cancelRequest` exactly once per request chain. Semantics are kept predictable: - Root future `cancel(boolean)` delegates to `cancelRequest(...)` (sends protocol cancel). - Derived stages do not auto-send on `cancel(boolean)`; callers use `cancelRequest(...)` explicitly.
373d1d0 to
1e2fae8
Compare
|
I made it optional. default behavior is to send the cancel request to the LSP server an wait for the cancel response which gracefully cancels the root future and it's depending stages. using cancelRequest(...,true) you can now force immediate cancellation of the root future and the chain without waiting for the cancellation response. WDYT? |
|
Makes sense to me, thanks a lot for the improvements! Just a thought (I'm not requesting any change now, just would like to to discuss it with you): the Javadoc for the Another thought: it might probably make sense to allow for optional cancellation of a dependent future when calling These thoughts together lead me to the following design proposal. What if It seems that this design can simplify the Use cases:
|
- Split wire cancel from local cancel semantics - Add getRoot() to access the root request future - Add cancelRequest() that sends $/cancelRequest once (idempotent), without cancelling any future
|
I changed it accordingly.
Additionally |
|
@sebthom Thank you very much for all the effort! I've added a separate test to better isolate the fast-cancel case and also inlined the private methods in Please have a look and if you are fine with my updates, I'll be happy to approve and merge this PR. Thanks again! |
|
LGTM! Thanks for the conversation! |
|
Great! Thank you! 👍 |
|
Just a note that I'm looking at I does not fail locally upon many re-runs (on macOS), but something seems to be flaky. Unfortunately, I don't have much time right now, but will return to it, probably tomorrow. |
|
@sebthom Thanks for looking into the issue. As far as I understand, attempting to cancel a request is inherently racy with regard to the request completion. For example, the request might complete before the cancel notification arrives. This is normal, and should be expected. Actually, attempting to cancel an ordinary Therefore, I can see no problem with the code of this PR in this regard. In other words, I don't think that the changes proposed in #909 are really necessary or even desired. Perhaps the test itself expects too much, let's try to take a deeper look at it. |
|
Yes, the problem has been lurking in To verify it, check out 4e0cc84 (the last commit before merging this PR), and insert The test will consistently fail after that. To fix it, the test should expect not only I'll submit a PR with the fix. |
Return a
JsonRpcRequestFuturefromRemoteEndpoint.request(...), enablingcancelRequest(boolean)to send$/cancelRequestexactly once per request chain.Semantics are kept predictable:
cancel(boolean)delegates tocancelRequest(...)(sends protocol cancel).cancel(boolean); callers usecancelRequest(...)explicitly.This PR addresses #423 and would also greatly simplify future handling in LSP4E.
You can now do
endpoint.request("foo", "myparam").thenApply(..).thenCompose(...).thenAccept(...).cancelRequest(true)to cancel the complete future chain. I believe this also makes the cumbersomeorg.eclipse.lsp4j.jsonrpc.CancelChecker/org.eclipse.lsp4j.jsonrpc.FutureCancelCheckerin a lot of cases obsolete.