4 ms·
>But a LSP mostly deals with a single request at a time by a single client. Not really —- there’s bowl of spaghetti worth of concurrency in LSP. All of the fol
by matklad 5y ago
>But a LSP mostly deals with a single request at a time by a single client.
Not really —- there’s bowl of spaghetti worth of concurrency in LSP. All of the following things can happen at the same time, and they use the same state:
* several read-only requests from the client (compute completion *and* highlighting)
* write request from the client (the user typed a comment in Cargo.toml)
* write request from file system (user switched branches can Cargo.lock is now different)
* background project update (cargo metadata finished with a new project model)
* background compiler update (cargo check emitted a new diagnostic)
* updates on background “indexing” which were kicked in quiescent state
That’s significantly more logical concurrency than in a typical HTTP server, where each request is conceptually independent from every other and all the hard synchronization bits lie in the database.
To manage this complexity, csp-style APIs (async/await and blocking threads) don’t really work, as there’s too much fundamental shared mutable state. What sort-of-works (but still is complex) is an explicit actor model, where you manually code the state machine and explicitly resolve the conflicts of the style “ok, I got results from cargo metadata, so I could spawn cargo check, but I also know that the user changed Cargo.toml in the meantime, so the results of metadata are actually stale and I better re-run that”.