Skip to content

Keep LSP workspace preparation off the protocol loop #506

Description

@purefunctor

Follow-up opportunity

Nonblocking architecture/performance follow-up from #505, verified at 429c883a. The prepared-workspace handoff is a useful boundary, but expensive preparation still runs synchronously on the protocol thread. This is confirmed by the call path; no large-workspace latency benchmark was run for this review.

Evidence

  • iris-lsp::start creates a current-thread Tokio runtime.
  • initialized and finish_workspace_configuration call apply_configuration_inner through synchronous router notification/event handlers in compiler-bin/iris-lsp/src/server.rs.
  • apply_configuration_inner performs discovery, source reconfiguration preparation, and initial build_initial before returning. discover_manual also waits for std::process::Command::output() synchronously.
  • build_initial / query_package waits for Rayon package execution; query_package at lines 330–341 drives queries through JavaScript generation. Parallel package work does not make the calling protocol handler asynchronous.
  • Introduced by package-scheduled LSP bootstrap, retained after workspace runtime encapsulation. The test requests_are_cancelled_while_the_workspace_is_loading checks a waiting State directly, not protocol responsiveness while preparation is executing.

Why it matters

While a preparation handler is running, the main loop cannot service incoming requests, shutdown, or newer configuration messages. The existing waiting-state rejection and notification queue help while waiting for client configuration, but cannot run concurrently with synchronous preparation. Slow source commands can extend this indefinitely.

Bounded completion criteria

  • Move discovery/initial compilation and source-reconfiguration preparation into owned background work; return results through a generation-tagged event and commit only a current result on the protocol thread.
  • Preserve ordered pending notifications, open buffers, previous-workspace retention on preparation failure, and the existing distinction between preparation and delivery failure.
  • Add a protocol E2E test with deterministically blocked preparation that proves the loop can respond before preparation is released, and that a superseded result cannot replace the newest configuration. Define shutdown cleanup for outstanding preparation/source-command work.

Duplicate check: searched open and closed issues for initialization, blocking, responsiveness, and configuration. Closed #47 concerns cancellation versus file locking, and closed #497 establishes workspace settings; neither covers asynchronous preparation.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestlanguage-serverRelated to the language server

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions