Skip to content

[ty] Add background request task support #19041

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

Merged
merged 3 commits into from
Jul 3, 2025

Conversation

dhruvmanila
Copy link
Member

Summary

This PR adds a new trait to support running a request in the background.

Currently, there exists a BackgroundDocumentRequestHandler trait which is similar but is scoped to a specific document (file in an editor context). The new trait BackgroundRequestHandler is not tied to a specific document nor a specific project but it's for the entire workspace.

This is added to support running workspace wide requests like computing the workspace diagnostics or workspace symbols.

Note: There's a slight difference with what a "workspace" means between the server and ty. Currently, there's a 1-1 relationship between a workspace in an editor and the project database corresponding to that workspace in ty but this could change in the future when Micha adds support for multiple workspaces or multi-root workspaces.

The data that would be required by the request handler (based on implementing workspace diagnostics) is the list of databases (ProjectDatabse) corresponding to the projects in the workspace and the index (Index) that contains the open documents. The WorkspaceSnapshot represents this and is passed to the handler similar to DocumentSnapshot.

Test Plan

This is used in implementing the workspace diagnostics which is where this is tested.

@dhruvmanila dhruvmanila added internal An internal refactor or improvement ty Multi-file analysis & type inference labels Jun 30, 2025
Copy link
Contributor

github-actions bot commented Jun 30, 2025

mypy_primer results

Changes were detected when running on open source projects
operator (https://github.com/canonical/operator)
- TOTAL MEMORY USAGE: ~106MB
+ TOTAL MEMORY USAGE: ~97MB

trio (https://github.com/python-trio/trio)
-     memo fields = ~156MB
+     memo fields = ~142MB

isort (https://github.com/pycqa/isort)
- TOTAL MEMORY USAGE: ~80MB
+ TOTAL MEMORY USAGE: ~88MB

vision (https://github.com/pytorch/vision)
- TOTAL MEMORY USAGE: ~334MB
+ TOTAL MEMORY USAGE: ~368MB

mkdocs (https://github.com/mkdocs/mkdocs)
-     memo fields = ~106MB
+     memo fields = ~97MB

tornado (https://github.com/tornadoweb/tornado)
- TOTAL MEMORY USAGE: ~156MB
+ TOTAL MEMORY USAGE: ~171MB

bandersnatch (https://github.com/pypa/bandersnatch)
-     memo fields = ~72MB
+     memo fields = ~66MB

paasta (https://github.com/yelp/paasta)
-     memo fields = ~156MB
+     memo fields = ~171MB

django-stubs (https://github.com/typeddjango/django-stubs)
- TOTAL MEMORY USAGE: ~171MB
+ TOTAL MEMORY USAGE: ~189MB

meson (https://github.com/mesonbuild/meson)
-     memo fields = ~334MB
+     memo fields = ~304MB

@dhruvmanila dhruvmanila requested review from BurntSushi and removed request for dcreager, carljm, sharkdp and AlexWaygood June 30, 2025 13:48
Copy link
Member

@BurntSushi BurntSushi left a comment

Choose a reason for hiding this comment

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

Nice! My only comments are requesting docs, probably because I'm somewhat unfamiliar with this part of the LSP. :-)

@@ -135,7 +135,52 @@ where
}))
}

fn background_request_task<R: traits::BackgroundDocumentRequestHandler>(
#[expect(dead_code)]
Copy link
Member

Choose a reason for hiding this comment

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

Could you add a comment saying why this code is kept around even though it isn't used?

Copy link
Member Author

Choose a reason for hiding this comment

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

I split the workspace diagnostics work into two PRs to ease up the review process. This is going to be used in the follow-up PR (#18939). Sorry, I should've highlighted this as a review comment!

snapshot: WorkspaceSnapshot,
client: &Client,
params: <<Self as RequestHandler>::RequestType as Request>::Params,
) -> super::Result<<<Self as RequestHandler>::RequestType as Request>::Result>;
Copy link
Member

Choose a reason for hiding this comment

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

One thing I'd find helpful here is some prose (perhaps on the module doc) that briefly explains the traits here and how they're connected.

If you think this code is going to be heavily refactored soon, then it might not make sense to add docs.

Copy link
Member Author

Choose a reason for hiding this comment

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

Definitely! Most of this stuff is currently in my and Micha's mind but it would be useful to have it written down. I'll prioritize it soon as there are now more people who'll be working on the server.

@dhruvmanila dhruvmanila force-pushed the dhruv/background-request-handler branch from 0e72155 to 1252436 Compare July 3, 2025 10:57
@dhruvmanila dhruvmanila enabled auto-merge (squash) July 3, 2025 10:59
@dhruvmanila dhruvmanila merged commit a95c18a into main Jul 3, 2025
35 checks passed
@dhruvmanila dhruvmanila deleted the dhruv/background-request-handler branch July 3, 2025 11:01
Copy link

codspeed-hq bot commented Jul 3, 2025

CodSpeed WallTime Performance Report

Merging #19041 will degrade performances by 4.82%

Comparing dhruv/background-request-handler (1252436) with main (e212dc2)

Summary

❌ 1 regressions
✅ 7 untouched benchmarks

⚠️ Please fix the performance issues or acknowledge them on CodSpeed.

Benchmarks breakdown

Benchmark BASE HEAD Change
multithreaded[pydantic] 321 ms 337.3 ms -4.82%

/// A request handler that can be run on a background thread.
pub(super) trait BackgroundRequestHandler: RetriableRequestHandler {
fn run(
snapshot: WorkspaceSnapshot,
Copy link
Member

Choose a reason for hiding this comment

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

I wonder if we should call this SessionSnapshot instead. It's unfortunate that the LSP specification made such a mess of the term workspace (which can refer to an open folder, or all open foldlers).

@@ -223,6 +224,14 @@ impl Session {
self.index().key_from_url(url)
}

pub(crate) fn take_workspace_snapshot(&self) -> WorkspaceSnapshot {
WorkspaceSnapshot {
projects: AssertUnwindSafe(self.projects.values().cloned().collect()),
Copy link
Member

Choose a reason for hiding this comment

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

I'd suggest removing the AssertUnwindSafe here and insteaed wrap the entire snapshot in crates/ty_server/src/server/api.rs in an AssertUnwindSafe and add a comment saying that it's safe to move it across unwind boundaries because the value isn't used after unwinding.

Copy link
Member Author

Choose a reason for hiding this comment

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

That would mean that the snapshot parameter type of BackgroundRequestHandler::run would need to be AssertUnwindSafe<SessionSnapshot>. Or, are you suggesting to wrap the AssertUnwindSafe on the entire closure that is the first argument to catch_unwind?

Copy link
Member Author

@dhruvmanila dhruvmanila Jul 7, 2025

Choose a reason for hiding this comment

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

The former doesn't seems to work as the compiler still errors stating that some reference may not be safe to be transferred across the catch_unwind boundary.

Edit: Nevermind, it works.

@MichaReiser
Copy link
Member

Nice!

@dhruvmanila
Copy link
Member Author

Addressed these review comments in #19177.

dhruvmanila added a commit that referenced this pull request Jul 7, 2025
This PR addresses the post-merge review comments from
#19041, specifically it:
- Rename `WorkspaceSnapshot` to `SessionSnapshot`
- Rename `take_workspace_snapshot` to `take_session_snapshot`
- Rename `take_snapshot` to `take_document_snapshot`
- Move `AssertUnwindSafe` closer to the `catch_unwind` call which
requires the assertion
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
internal An internal refactor or improvement ty Multi-file analysis & type inference
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants