Closed ratmice closed 2 years ago
FWIW, I'm going to go ahead and close this, the way I got it working was basically described in Edit 2
: using a tokio::sync::oneshot
, One nice thing about this is that oneshot::Sender::send
is sync so the subjugate threads can just respond directly to the Backend
, so the Response task is kept out of the loop unless the subjugate thread needs to invoke the client directly.
This in some ways seem similar to some of the things discussed in issue #231 where requests could be passed a cancellation token, My usage of tower-lsp is a little weird due to some
!Send + !Sync
variables, these variables have to live off in their own threads. The mainBackend
implementingLanguageClient
keeps a channel to send these threads messages.It then creates another thread which has a clone of
Client
which deals with receiving all the responses from all the threads and sending them back to the client. This works okay, until you need to deal with a request with a response, in implementing acustom_method()
it can be difficult to obtain the value that needs to be returned fromBackend
itself.Part of the reasoning behind the response thread is just that I don't see a nice way to receive from within
Backend
. e.g. toselect!
on both incomingjsonrpc
and subjugate thread channels, since this is hidden within theserve
function, But that would present an alternate way of responding, If backend had a good way of also receiving from channels, There wouldn't actually be any issue.mpsc::Sender
one for each subjugate thread)!Send + !Sync
value,mpsc::Receiver
from backend,mpsc::Sender
to Response thread)mpsc::Receiver
).The communications topology in particular looks like: Client -> Backend -> Subjugate thread -> Response task -> Client
In #231 it was discussed that requests could be given a separate cancellation token as a part of the request. I was thinking perhaps you could do a similar thing, instead of returning from the custom method a value, a variation of
custom_method
which gets both the params and aResponseToken
, which it could pass to various responders.P.S. sorry if this is a bit long & quite specific to the constraints upon which my implementation finds itself in
Edit: Making some clarifications about 'Response task', previously I had referred to this as 'Response thread', Edit 2: After thinking about it, perhaps my Backend can allocate a future, pass it through the communications channels, then when it arrives back in the async Response Task it becomes ready, and thus no actual modifications are needed in this case, because I may be able to make a
ResponseToken
without it actually being passed in fromcall
.