Skip to content

feat: workspace symbols warmup (Phase 2) - #158

Draft
AlexCannonball wants to merge 6 commits into
coder3101:mainfrom
AlexCannonball:feat/workspace-symbols-warmup
Draft

AlexCannonball wants to merge 6 commits into
coder3101:mainfrom
AlexCannonball:feat/workspace-symbols-warmup

Conversation

@AlexCannonball

Copy link
Copy Markdown
Contributor

Improvements related to Phase 2 from #130

@AlexCannonball

AlexCannonball commented Aug 11, 2026 •

Copy link
Copy Markdown
Contributor Author

At the moment still a very early attempt to implement eager warmup + lazy query evaluation from #130 (comment)

TODO list from the top of my head:

@AlexCannonball

Copy link
Copy Markdown
Contributor Author

Quick update on Phase 2 refactoring:

I'm currently pushing all heavy synchronous workloads (Tree-sitter processing, WalkDir, protoc, and clang-format) completely out of the main current_thread executor.

As expected, introducing async and graceful cancellation has deeply "infected" the entire codebase.

Right now, the IDE is reporting 100+ cascading type mismatch and lifetime errors.

I am currently grinding through these compiler errors layer by layer to align all the type boundaries and will continue pushing updates to this PR as soon as the core compilation passes. Still on it!

@coder3101

Copy link
Copy Markdown
Owner

Are you still working on this?

@AlexCannonball

Copy link
Copy Markdown
Contributor Author

Hello @coder3101

Yes, I do. Currently I'm trying to switch LSP notification handling to async. The order of notifications must be preserved and async-lsp only supports synchronous notification handler. So my attempt is to use the unbounded mpsc channel (synchronous tx, async handlers for rx).

@AlexCannonball
AlexCannonball force-pushed the feat/workspace-symbols-warmup branch from 74ed283 to 3a4bdcf Compare October 6, 2026 17:06
@AlexCannonball

AlexCannonball commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor Author

@coder3101 Hello, I've updated the draft to share some progress.

async-ification takes more time than I expected. Still in the middle of deep refactoring, still has compilation errors, but now I feel that some concepts look more realistic:

  • Notification worker.
    • Add the client capabilities for the file watcher registration.
  • Cancellation topology.
  • src/state/mod.rs the method query_documents_batch looks promising: batching, cancellation, shared futures, progress reporting and the resulting futures stream (hopefully it unlocks the partial result feature).

I will also comment some interesting findings in separate line comments.

So far I'm breaking down src/lsp.rs into distinct submodules for proper LSP request handling (some are already placed in src/server/request/).

src/state/mod.rs needs a cleanup as well. Will do it later.

I understand that currently import and grammar diagnostics probably won't work. First, I'd like to compile and test the metamodel cache state and the notification edge cases.

Comment thread src/document/syntax.rs
Comment thread src/formatter/clang.rs
.output()
.ok()?;
let wait_future = child.wait_with_output();
let timeout_result = tokio::time::timeout(CLANG_FORMAT_TIMEOUT, wait_future).await;

@AlexCannonball AlexCannonball Oct 6, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Improvements:

  • async, not blocking the main thread
  • using stdin input, so a temp file isn't needed
  • added timeout protection

Comment thread src/formatter/mod.rs

pub use clang::ClangFormatter;

pub trait ProtoFormatter: Sized {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Haven't discovered this trait purpose.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Could have been used for unifying other formatters like buf, clangd etc.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thank you! As I remember, There were some troubles with the async trait. I'll keep this open and will try to restore the trait after the cache and async-ification are stabilized.

Comment thread src/main.rs
Comment thread src/protoc.rs
// Run protoc and capture output
match cmd.output() {
Ok(output) => {
match tokio::time::timeout(PROTOC_TIMEOUT, cmd.kill_on_drop(true).output()).await {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

  • not blocking the main thread
  • timeout protection

Comment thread src/server.rs

pub struct ProtoLanguageServer {
pub client: ClientSocket,
pub(crate) log_handle: log::LogReloadHandle,

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Moved this to the notification worker.

Comment thread src/formatter/clang.rs Outdated
}
}

const CLANG_FORMAT_TIMEOUT: Duration = Duration::from_secs(2);

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Should be configurable from config file, on slower systems with large file 2s might be too low.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Maybe just increasing the timeout from 2 seconds to 5–10 seconds will be enough?

@asharkhan3101 asharkhan3101 Oct 7, 2026 •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

if not configurable, setting to 5 second is fine, given its async anyways.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thank you, I've set it to 5: 51e4c92

I'm not sure about the setting(s) because having too many config options isn't always good for users. Also it increases the complexity:

  • Validation and boundaries
  • The main TOML config
  • Client settings
  • CLI args
  • ENV

Anyways, we can add a setting later as a follow-up, if needed.

Comment thread src/document/syntax.rs
Comment thread src/protoc.rs Outdated
file_path: &str,
include_paths: &[String],
) -> Vec<Diagnostic> {
const PROTOC_TIMEOUT: Duration = Duration::from_secs(2);

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Same as ClangFormatter Timeout

Comment thread src/server.rs Outdated
pub shutdown_received: bool,
pub configs: Arc<RwLock<WorkspaceProtoConfigs>>,
pub shutdown_token: CancellationToken,
notification_tx: UnboundedSender<Notification>,

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Why Unbounded?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thank you, it's a very good question. I guess I was too optimistic, like, "if everything works fine, the unbounded channel will never consume too many memory"😀

I've changed it to a fail-fast bounded sender, please take a look: 44d7cbf


https://docs.rs/async-lsp/latest/async_lsp/router/struct.Router.html#method.notification

Also, since async-lsp routes notifications through a synchronous API handler, we can't legitimately .await on a full bounded channel without completely stalling the main events loop or introducing heavy overengineering. A fail-fast try_send combined with an explicit WouldBlock error seems to be the most pragmatic and reliable approach here.

A fail-fast strategy for the notification worker channel.
Set `clang-format` and `protoc` run timeout to 5 seconds.
Subscribe to the client file watchers and skip reporting progress if the
client doesn't support `window/workDoneProgress/create`
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