vs-streamjsonrpc icon indicating copy to clipboard operation
vs-streamjsonrpc copied to clipboard

Add support for Timeouts

Open AdamoT opened this issue 4 years ago • 1 comments

It seems the library doesn't support timeouts at the moment which is very cumbersome if there are communication issues or errors on the other side. Assume there is a client that invokes rpc expecting a response: var response = await rpc.InvokeAsync<string>("Echo", "Hello World"); If the server is connected but doesn't process the request properly, this call will never end blocking further instructions on the client. Even if the above is changed to use cancellationToken:

var cancellation = new CancellationTokenSource(5000);
var response = await rpc.InvokeWithCancellationAsync<string>("Echo", new[] { "Hello World" }, cancellation.Token);

The request is cancelled after 5s but the Task would still never end (this is documented behaviour but doesn't fix the described issue).

An easy solution would be to add e.g. a ReceiveTimeOut at JsonRpc class level, periodically check all pending requests and set TimeOutException on all timeouted requests.

Btw. it is really great library, welly well structured and written! :)

AdamoT avatar Oct 15 '21 11:10 AdamoT

It sounds like you want to abandon the request and move on given some timeout. If so, using a CancellationToken as you're doing is a good start since it will indicate to the RPC server that it can cancel any pending processing of that request. To also bail out early on the client side, tack on WithCancellation:

var cancellation = new CancellationTokenSource(5000);
var response = await rpc.InvokeWithCancellationAsync<string>("Echo", new[] { "Hello World" }, cancellation.Token).WithCancellation(cancellation.Token);

That extension method turns any async method into a "exit immediately when I cancel" method.

AArnott avatar Oct 25 '21 21:10 AArnott

While WithCancellation generally works it gets tedious do add it instead of using the regular CancellationToken parameter.

It is also unclear how to gracefully terminate the whole RPC setup when remote party stops responding while using WithCancellation.

Also, it throws off some static analysis tools when you call it on a task returned from a method that already had CancellationToken parameter.

The quirk is also easy to forget about.

lostmsu avatar Dec 16 '23 00:12 lostmsu

WithCancellation is not equivalent to passing in a cancellation token, just to be clear.

The WithCancellation extension method, which is orthogonal to StreamJsonRpc by the way, does not cancel the request. It merely stops the client from waiting any more and throws OCE in order to break out of the await for the response. It's a break-glass type thing when you need to ensure you stop waiting for a response without waiting for the server to acknowledge the cancellation. And in such cases, it's usually a good idea to also pass the cancellation token in the original request as well so that at least the server can be notified that the client isn't interested in the response any more rather than toil on without knowing.

AArnott avatar Jan 03 '24 16:01 AArnott