atom-languageclient
atom-languageclient copied to clipboard
Keep server alive for a project
In Scala projects it makes sense to keep language server alive for the whole project, because the startup is quite slow.
Currently, server is started only when I open a Scala source, then every time I close the last tab with Scala source, server is stopped and if I open a new tab, new server is started again.
I'd like to implement a workflow where server is started when I open a new project (in Atom terminology) which looks like a Scala project (checking sbt or ENSIME configuration files presence), then stop it only when the project is removed from the workspace.
I thought at first, that this method could be helpful:
https://github.com/atom/atom-languageclient/blob/1153b29f94ab0c7ff588445ac1ac6622460d124b/lib/auto-languageclient.js#L75-L76
But this is about adding condition on an editor, not workspace or project. I also see that server is considered unused and is stopped when all associated editors are closed in
https://github.com/atom/atom-languageclient/blob/1153b29f94ab0c7ff588445ac1ac6622460d124b/lib/server-manager.js#L158
But I don't know how to override this behavior for my client. Is it possible to do? And if not, would it be viable to support such workflow?
:+1: Ensime server requires some time to start, so it's quite important not to relaunch it.
Hi, I've been toying with a language server for a couple of days and I wanted a similar configuration. I have something that works-ish, so I'll share it in case it's useful.
- The server is started and stopped independently; it has to be running for atom-languageclient to work.
- In my
AutoLanguageClient
, I usestartServerProcess
to spawn a process using another JS file, much like the example:
startServerProcess () {
const scriptPath = require.resolve('my-client/lib/client_process.js')
return super.spawnChildNode([scriptPath])
}
- In
client_process.js
, I open a socket connection to the already-running language server. I pipe the process's STDIN and STDOUT to the socket, so that the client process is a basically pipe between Atom and the language server. - The client process also handles disconnects & reconnects, so that I can restart the server without crashing Atom.
I have a few outstanding issues:
- It seems like I should be able to use the
socket
connection type from this library, but I couldn't get it to work right with reconnections. - I'd like to improve the experience when the language server is not running. Right now, it's just silent.
- I'd like to improve
startServerProcess
to handle connection failure by re-starting the language server, but I haven't done that yet, so you have to start the server separately.
I'm a bit out of my depth on this, but if you have any feedback, I'd love to hear it, or if you're interested, I can try to share some code!
I think this is tied up with https://github.com/atom/atom-languageclient/issues/71 and the various connection problems.
My plan is to make the servers restartable from code and to provide an easy way for ide-x authors to specify how long to idle before shutting them down (or opt out entirely to do it themselves).
Hoping to begin working on this tomorrow as well as having auto-restarting on connection/server failure.
My plan is to make the servers restartable from code and to provide an easy way for ide-x authors to specify how long to idle before shutting them down (or opt out entirely to do it themselves).
@damieng although this functionality is useful on its own, I don't see how it addresses the described use-case for server lifecycle tied to projects. It requires altering current logic of stopUnusedServers
: instead of tracking whether there are any editors bound to a server with _editorToServer
map, it should track whether the project root folder is still open.
In the end, when you launch a language server, you do it for some notion of a "project" or "workspace" (rootUri
in the initialization request). So I think that in general server lifecycle managed by server-manager should be more project-oriented instead of files/editors/tabs-oriented.
I think that the latter works well only for scripting interpreted languages, which don't require any kind of project setup.
So the possibilities as far as I see it are:
- Always open on project open/add folder if a specific file is present (e.g. a project definition) and only close if Atom closes or the project folder is removed
- Automatically shutdown last edited file but only after a delay (and if another file opens during that delay the stop never happens)
- Custom logic to determine when to start and stop a server (what information would they need from atom-languageclient)
Always open on project open/add folder if a specific file is present (e.g. a project definition) and only close if Atom closes or the project folder is removed
That's exactly what I wanted opening this issue. I would only make this predicate not too narrow, i.e. not just "specific file is present", but a general atom$Project => boolean
. Similarly to the current:
https://github.com/atom/atom-languageclient/blob/f4c1ba242f6f9191b4ac1ce71258f49f61f877c3/lib/auto-languageclient.js#L81
But
shouldStartForProject(editor: atom$Project): boolean
Automatically shutdown last edited file but only after a delay (and if another file opens during that delay the stop never happens)
Independently of the previous alternative I see it useful for scripting languages (or markup languages) which don't need a project definition (i.e. server works with each source file independently).
Development of atom-languageclient has officially moved to https://github.com/atom-ide-community/atom-languageclient 🎉
If this is still an issue please consider opening an issue on that repo.