Skip to content

Commit 67c5574

Browse files
simplify salsa db management with Clone + Arc<Mutex<Session>> (#194)
1 parent b90862d commit 67c5574

File tree

6 files changed

+47
-478
lines changed

6 files changed

+47
-478
lines changed

crates/djls-server/src/server.rs

Lines changed: 28 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use std::sync::Arc;
33

44
use djls_workspace::paths;
55
use djls_workspace::FileKind;
6-
use tokio::sync::RwLock;
6+
use tokio::sync::Mutex;
77
use tower_lsp_server::jsonrpc::Result as LspResult;
88
use tower_lsp_server::lsp_types;
99
use tower_lsp_server::Client;
@@ -19,7 +19,7 @@ const SERVER_VERSION: &str = "0.1.0";
1919
pub struct DjangoLanguageServer {
2020
#[allow(dead_code)] // will be needed when diagnostics and other features are added
2121
client: Client,
22-
session: Arc<RwLock<Option<Session>>>,
22+
session: Arc<Mutex<Session>>,
2323
queue: Queue,
2424
_log_guard: WorkerGuard,
2525
}
@@ -29,7 +29,7 @@ impl DjangoLanguageServer {
2929
pub fn new(client: Client, log_guard: WorkerGuard) -> Self {
3030
Self {
3131
client,
32-
session: Arc::new(RwLock::new(None)),
32+
session: Arc::new(Mutex::new(Session::default())),
3333
queue: Queue::new(),
3434
_log_guard: log_guard,
3535
}
@@ -38,34 +38,22 @@ impl DjangoLanguageServer {
3838
pub async fn with_session<F, R>(&self, f: F) -> R
3939
where
4040
F: FnOnce(&Session) -> R,
41-
R: Default,
4241
{
43-
let session = self.session.read().await;
44-
if let Some(s) = &*session {
45-
f(s)
46-
} else {
47-
tracing::error!("Attempted to access session before initialization");
48-
R::default()
49-
}
42+
let session = self.session.lock().await;
43+
f(&session)
5044
}
5145

5246
pub async fn with_session_mut<F, R>(&self, f: F) -> R
5347
where
5448
F: FnOnce(&mut Session) -> R,
55-
R: Default,
5649
{
57-
let mut session = self.session.write().await;
58-
if let Some(s) = &mut *session {
59-
f(s)
60-
} else {
61-
tracing::error!("Attempted to access session before initialization");
62-
R::default()
63-
}
50+
let mut session = self.session.lock().await;
51+
f(&mut session)
6452
}
6553

6654
pub async fn with_session_task<F, Fut>(&self, f: F)
6755
where
68-
F: FnOnce(Arc<RwLock<Option<Session>>>) -> Fut + Send + 'static,
56+
F: FnOnce(Arc<Mutex<Session>>) -> Fut + Send + 'static,
6957
Fut: Future<Output = anyhow::Result<()>> + Send + 'static,
7058
{
7159
let session_arc = Arc::clone(&self.session);
@@ -89,8 +77,8 @@ impl LanguageServer for DjangoLanguageServer {
8977
let encoding = session.position_encoding();
9078

9179
{
92-
let mut session_lock = self.session.write().await;
93-
*session_lock = Some(session);
80+
let mut session_lock = self.session.lock().await;
81+
*session_lock = session;
9482
}
9583

9684
Ok(lsp_types::InitializeResult {
@@ -137,19 +125,16 @@ impl LanguageServer for DjangoLanguageServer {
137125

138126
self.with_session_task(move |session_arc| async move {
139127
let project_path_and_venv = {
140-
let session_lock = session_arc.read().await;
141-
match &*session_lock {
142-
Some(session) => session.project().map(|p| {
143-
(
144-
p.path().display().to_string(),
145-
session
146-
.settings()
147-
.venv_path()
148-
.map(std::string::ToString::to_string),
149-
)
150-
}),
151-
None => None,
152-
}
128+
let session_lock = session_arc.lock().await;
129+
session_lock.project().map(|p| {
130+
(
131+
p.path().display().to_string(),
132+
session_lock
133+
.settings()
134+
.venv_path()
135+
.map(std::string::ToString::to_string),
136+
)
137+
})
153138
};
154139

155140
if let Some((path_display, venv_path)) = project_path_and_venv {
@@ -163,17 +148,12 @@ impl LanguageServer for DjangoLanguageServer {
163148
}
164149

165150
let init_result = {
166-
let mut session_lock = session_arc.write().await;
167-
match &mut *session_lock {
168-
Some(session) => {
169-
if let Some(project) = session.project_mut().as_mut() {
170-
project.initialize(venv_path.as_deref())
171-
} else {
172-
// Project was removed between read and write locks
173-
Ok(())
174-
}
175-
}
176-
None => Ok(()),
151+
let mut session_lock = session_arc.lock().await;
152+
if let Some(project) = session_lock.project_mut().as_mut() {
153+
project.initialize(venv_path.as_deref())
154+
} else {
155+
// Project was removed between read and write locks
156+
Ok(())
177157
}
178158
};
179159

@@ -189,10 +169,8 @@ impl LanguageServer for DjangoLanguageServer {
189169
);
190170

191171
// Clear project on error
192-
let mut session_lock = session_arc.write().await;
193-
if let Some(session) = &mut *session_lock {
194-
*session.project_mut() = None;
195-
}
172+
let mut session_lock = session_arc.lock().await;
173+
*session_lock.project_mut() = None;
196174
}
197175
}
198176
} else {

crates/djls-server/src/session.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ use url::Url;
2020
/// - Workspace operations (delegated to the Workspace facade)
2121
///
2222
/// All document lifecycle and database operations are delegated to the
23-
/// encapsulated Workspace, which provides thread-safe Salsa database
24-
/// management with proper mutation safety through `StorageHandleGuard`.
23+
/// encapsulated Workspace, which provides Salsa database management
24+
/// using the built-in Clone pattern for thread safety.
2525
pub struct Session {
2626
/// The Django project configuration
2727
project: Option<DjangoProject>,

crates/djls-workspace/src/db.rs

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -111,20 +111,6 @@ impl Database {
111111
}
112112
}
113113

114-
pub fn from_storage(
115-
storage: salsa::Storage<Self>,
116-
file_system: Arc<dyn FileSystem>,
117-
files: Arc<DashMap<PathBuf, SourceFile>>,
118-
) -> Self {
119-
Self {
120-
storage,
121-
fs: file_system,
122-
files,
123-
#[cfg(test)]
124-
logs: Arc::new(Mutex::new(None)),
125-
}
126-
}
127-
128114
/// Read file content through the file system.
129115
pub fn read_file_content(&self, path: &Path) -> std::io::Result<String> {
130116
self.fs.read_to_string(path)
@@ -200,13 +186,6 @@ impl Database {
200186
new_rev
201187
);
202188
}
203-
204-
/// Get a reference to the storage for handle extraction.
205-
///
206-
/// This is used by `Session` to extract the [`StorageHandle`](salsa::StorageHandle) after mutations.
207-
pub fn storage(&self) -> &salsa::Storage<Self> {
208-
&self.storage
209-
}
210189
}
211190

212191
#[salsa::db]

crates/djls-workspace/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ pub mod encoding;
1919
mod fs;
2020
mod language;
2121
pub mod paths;
22-
mod storage;
2322
mod workspace;
2423

2524
use std::path::Path;

0 commit comments

Comments
 (0)