New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Maintenance: Tidy up server lifecycle #520
Maintenance: Tidy up server lifecycle #520
Conversation
Avoid mutating initializeFuture from within blocks chained onto initializeFuture itself. There is no need to e.g. call initializeFuture.completeExceptionally from within an exceptionallyBlock chained onto initializeFuture! If that block is hit the future is already in a 'completed, exceptionally' state.
Split most of the low-level startup/shutdown detail out of LanguageServerWrapper so that LSW's lifecycle can be simplified to stopped->starting->started->stopping with atomic transitions between the stages.
The latest commit splits a lot of the lifecycle code out of LanguageServerWrapper. It's not as drastic a change as it looks, as it mostly involves just moving the low-level code in chained futures out of Rationale:
Caveats:
|
@rubenporras @mickaelistria any general thoughts? Need to be very careful making changes to this logic, so I definitely don't think we should be in a hurry to merge any of this. On the other hand, the existing code has evolved quite a lot to the point where it is very hard to reason about the lifecycle, so I think sooner or later it would be good to bite the bullet and try and rationalise things. Would appreciate thoughts on this as a general approach. |
…tion Hadn't quite understood the existing logic. We cater for the fact that workspace folder capability can be dynamically registered and unregistered but if the server responds that it supports them in the initial server capabilities on startup then we deem that to be a permanent feature. This is quite important to the server lifecycle as a wrapper gets kept even when the server it manages has shut down (e.g. from idle timeout). Whether a server supports workspace folders is a key part of deciding whether a wrapper instance can be used for a particular document if that document is from a different project than the one the wrapper was started with.
Just fixed an issue with workspace folders. Of interest because it is related to the discussion about lifecycle and Two observations come to mind: we seem to be interpreting the 'workspace folders' capability slightly differently to the spec. AIUI, workspace folders are supported at basic level either as a yes or a no, and that doesn't change dynamically. The feature that can be added dynamically is subscription to the Secondly - what are we gaining from keeping wrappers around when the server is shut down? |
Can you please open a dedicated issue for that?
In case a LS instance or connection dies, then the wrapper is still supposed to be partly usable and to revive the LS. Usually, the LS keeps the same capabilities and so on, so we can keep using the wrapper to select the language servers that we will query for an operation or another even if this LS has died in the meantime. |
The initial target branch |
Further tweaks to server lifecycle code to make it a little simpler to follow.
Avoid mutating initializeFuture from within blocks chained onto initializeFuture itself. There is no need to e.g. call initializeFuture.completeExceptionally from within an exceptionallyBlock chained onto initializeFuture! If that block is hit the future is already in a 'completed, exceptionally' state.