Skip to content
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

Proxy for expensive API requests #736

Merged
merged 10 commits into from
May 30, 2024
Merged

Proxy for expensive API requests #736

merged 10 commits into from
May 30, 2024

Conversation

scohen
Copy link
Collaborator

@scohen scohen commented May 13, 2024

When doing complicated refactors, the language server will often spam remote_control with a ton of operations when the refactor is going on. These operations will slow down both the editor and remote_control so that it's not particularly usable. In order to mitigate this, certain operations, like project compilation, can be buffered and completed when the refactor has completed.

This PR implements a proxy module that buffers these complicated operations, and monitors the calling process. When that process exits, the buffered operations are emitted in remote_control, allowing them to complete without disrupting the refactor.

@scohen scohen requested review from zachallaun and scottming May 13, 2024 18:07
@scohen scohen force-pushed the api-proxy branch 2 times, most recently from 518cb51 to 476cd92 Compare May 13, 2024 23:43
@scohen
Copy link
Collaborator Author

scohen commented May 20, 2024

@zachallaun can you please respond to the comments?

@scohen scohen force-pushed the api-proxy branch 2 times, most recently from 4c93891 to 985e8a8 Compare May 21, 2024 22:17
@zachallaun
Copy link
Collaborator

@scohen I was having a hard time articulating my thoughts on the proxy state stuff, so I went ahead and implemented two changes that I think help to simplify things. They could be taken individually (with some changes), so I'd recommend looking at the two commits separately:

https://github.com/lexical-lsp/lexical/compare/api-proxy...zachallaun:lexical:za-api-proxy?expand=1

Copy link
Collaborator

@zachallaun zachallaun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made one other comment about a Lexical.Test.MfaSupport, which I don't think is being used. Otherwise looks good.

scohen and others added 7 commits May 24, 2024 17:21
When doing complicated refactors, the language server will often spam
remote_control with a ton of operations when the refactor is going on.
These operations will slow down both the editor and remote_control so
that it's not particularly usable. In order to mitigate this, certain
operations, like project compilation, can be buffered and completed when
the refactor has completed.

This PR implements a proxy module that buffers these complicated
operations, and monitors the calling process. When that process exits,
the buffered operations are emitted in remote_control, allowing them to
complete without disrupting the refactor.
* Use mfa record for proxied broadcasts

* Add sequence number to proxied mfa's to track order

---------

Co-authored-by: Zach Allaun <[email protected]>
@scottming
Copy link
Collaborator

To summarize my exploration today, I found that removing Build.with_lock indeed avoids the deadlock issue. However, occasionally the formatter fails to recognize .formatter.exs. I'm not sure if it's because my commit is missing something.

@scottming
Copy link
Collaborator

Additionally, I tried integrating this PR with the Rename module branch, and I found that the renaming can be completed instantly. However, we can't avoid a series of mix compile commands queuing up, which puts a heavy load on the CPU. The current Rename PR does not compile even once before the renaming is completed.

@scohen I hope you can take a look at this commit when you have time; maybe I'm using the API.Proxy method incorrectly.

@scohen
Copy link
Collaborator Author

scohen commented May 26, 2024

@scottming removing the locks is the likely cause for the queueing you’re seeing. That’s not the correct path forward

scohen added 3 commits May 28, 2024 18:27
In testing, I found two deadlocks. The first was that the build server
was using RemoteControl.call to invoke itself rather than
`GenServer.call`. This created an additional lock, and was
unnecessary, because it's running locally.

The second was more insidious. The proxy module made a bunch of
separate calls to other modules, which in turn woud call
`Build.with_lock`, which would then be run inside the proxy's
process. This would cause fairly frequent locks in the proxy process.
Moving these calls into tasks, fixes things, but creates the need for
an additional `draining` state of the proxy, which it enteres if there
are in-flight requests when `start_buffering` is called.
@scohen scohen merged commit 1e3804f into main May 30, 2024
9 checks passed
@scohen scohen deleted the api-proxy branch May 30, 2024 17:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants