Skip to content

Commit

Permalink
refactor: persist workspaces across connections (#5193)
Browse files Browse the repository at this point in the history
  • Loading branch information
arendjr authored Feb 25, 2025
1 parent 0750b40 commit 14ad3f5
Show file tree
Hide file tree
Showing 3 changed files with 244 additions and 143 deletions.
11 changes: 11 additions & 0 deletions .changeset/reuse_workspaces.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"@biomejs/biome": major
---

The Biome daemon now reuses its workspace across connections. This allows multiple clients to
reuse the same documents and other cached data that we extract from them.

This primarily affects our IDE extensions: If you open multiple IDEs/windows for the same project,
they'll connect to the same daemon and reuse each other's workspace.

The Biome CLI is unaffected unless you opt in with the `--use-server` argument.
22 changes: 13 additions & 9 deletions crates/biome_lsp/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use rustc_hash::FxHashMap;
use serde_json::json;
use std::panic::RefUnwindSafe;
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
use std::sync::{Arc, Mutex};
use std::sync::{Arc, Mutex, OnceLock};
use tokio::io::{AsyncRead, AsyncWrite};
use tokio::sync::Notify;
use tokio::task::spawn_blocking;
Expand Down Expand Up @@ -535,11 +535,11 @@ pub struct ServerFactory {
/// Synchronization primitive used to broadcast a shutdown signal to all
/// active connections
cancellation: Arc<Notify>,
/// Optional [Workspace] instance shared between all clients. Currently
/// this field is always [None] (meaning each connection will get its own
/// workspace) until we figure out how to handle concurrent access to the
/// same workspace from multiple client
workspace: Option<Arc<dyn Workspace>>,

/// [Workspace] instance shared between all clients.
///
/// Initialized when the first connection is created.
workspace: OnceLock<Arc<dyn Workspace>>,

/// The sessions of the connected clients indexed by session key.
sessions: Sessions,
Expand All @@ -559,7 +559,7 @@ impl ServerFactory {
pub fn new(stop_on_disconnect: bool) -> Self {
Self {
cancellation: Arc::default(),
workspace: None,
workspace: OnceLock::default(),
sessions: Sessions::default(),
next_session_key: AtomicU64::new(0),
stop_on_disconnect,
Expand All @@ -579,8 +579,8 @@ impl ServerFactory {
) -> ServerConnection {
let workspace = self
.workspace
.clone()
.unwrap_or_else(|| workspace::server_sync(fs));
.get_or_init(|| workspace::server_sync(fs))
.clone();

let session_key = SessionKey(self.next_session_key.fetch_add(1, Ordering::Relaxed));

Expand Down Expand Up @@ -673,3 +673,7 @@ impl ServerConnection {
.await;
}
}

#[cfg(test)]
#[path = "server.tests.rs"]
mod tests;
Loading

0 comments on commit 14ad3f5

Please sign in to comment.