Skip to content

Commit def9fba

Browse files
migrate all async tokio to server & swap to single-thread runtime (#149)
1 parent c29b268 commit def9fba

File tree

12 files changed

+46
-104
lines changed

12 files changed

+46
-104
lines changed

Cargo.toml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,12 @@ djls-templates = { path = "crates/djls-templates" }
1313
anyhow = "1.0"
1414
async-trait = "0.1"
1515
pyo3 = "0.24"
16-
pyo3-async-runtimes = "0.24"
1716
pyo3-build-config = "0.24"
1817
salsa = { git = "https://github.com/salsa-rs/salsa.git", rev = "7edce6e248f35c8114b4b021cdb474a3fb2813b3" }
1918
serde = { version = "1.0", features = ["derive"] }
2019
serde_json = "1.0"
2120
tempfile = "3.19"
2221
thiserror = "2.0"
23-
tokio = { version = "1.42", features = ["full"] }
24-
tower-lsp-server = { version = "0.21", features = ["proposed"] }
2522

2623
[workspace.lints.clippy]
2724
pedantic = { level = "warn", priority = -1 }

crates/djls-project/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ default = []
1010
[dependencies]
1111
pyo3 = { workspace = true }
1212
salsa = { workspace = true }
13-
tower-lsp-server = { workspace = true, features = ["proposed"] }
1413

1514
which = "7.0.1"
1615

crates/djls-server/Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ pyo3 = { workspace = true }
1717
salsa = { workspace = true }
1818
serde = { workspace = true }
1919
serde_json = { workspace = true }
20-
tokio = { workspace = true }
21-
tower-lsp-server = { workspace = true }
2220

23-
percent-encoding = "2.3"
21+
percent-encoding = "2.3.1"
22+
tokio = { version = "1.45.0", features = ["full"] }
23+
tower-lsp-server = { version = "0.21.1", features = ["proposed"] }
2424

2525
[build-dependencies]
2626
djls-dev = { workspace = true }

crates/djls-server/src/documents.rs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,6 @@ pub struct Store {
2525
}
2626

2727
impl Store {
28-
pub fn new() -> Self {
29-
Self {
30-
documents: HashMap::new(),
31-
versions: HashMap::new(),
32-
}
33-
}
34-
3528
pub fn handle_did_open(&mut self, db: &dyn Database, params: &DidOpenTextDocumentParams) {
3629
let uri = params.text_document.uri.to_string();
3730
let version = params.text_document.version;

crates/djls-server/src/lib.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,25 @@ mod server;
55
mod session;
66
mod workspace;
77

8-
pub use crate::server::DjangoLanguageServer;
8+
use anyhow::Result;
9+
use tower_lsp_server::LspService;
10+
use tower_lsp_server::Server;
11+
12+
use crate::server::DjangoLanguageServer;
13+
14+
pub fn run() -> Result<()> {
15+
let runtime = tokio::runtime::Builder::new_current_thread()
16+
.enable_all()
17+
.build()?;
18+
19+
runtime.block_on(async {
20+
let stdin = tokio::io::stdin();
21+
let stdout = tokio::io::stdout();
22+
23+
let (service, socket) = LspService::build(DjangoLanguageServer::new).finish();
24+
25+
Server::new(stdin, stdout, socket).serve(service).await;
26+
27+
Ok(())
28+
})
29+
}

crates/djls-server/src/queue.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ use tokio::sync::oneshot;
1919
/// required for self-referential `async` blocks.
2020
/// - `Box`: Allocates the `Future` on the heap.
2121
/// - `dyn Future`: Type erasure - hides the specific concrete `Future` type.
22-
/// - `+ Send`: Ensures the `Future` can be safely sent across threads.
22+
/// - `+ Send`: Ensures the `Future` can be safely sent across threads and required
23+
/// by the tower-lsp-server LSP server trait bounds, even in our single-threaded
24+
/// runtime.
2325
type TaskFuture = Pin<Box<dyn Future<Output = Result<()>> + Send>>;
2426

2527
/// Type alias for a type-erased, heap-allocated, Send-able closure that,
@@ -34,7 +36,8 @@ type TaskFuture = Pin<Box<dyn Future<Output = Result<()>> + Send>>;
3436
/// arguments.
3537
/// - `-> TaskFuture`: Specifies that calling the closure produces the type-erased future.
3638
/// - `+ Send + 'static`: Ensures the closure itself can be safely sent across
37-
/// threads and has a static lifetime (doesn't borrow short-lived data).
39+
/// threads and has a static lifetime (doesn't borrow short-lived data). Required
40+
/// for compatibility with our async runtime and LSP traits.
3841
type TaskClosure = Box<dyn FnOnce() -> TaskFuture + Send + 'static>;
3942

4043
/// A simple asynchronous task queue for sequential execution.
@@ -43,8 +46,9 @@ type TaskClosure = Box<dyn FnOnce() -> TaskFuture + Send + 'static>;
4346
/// to a dedicated worker task which executes them one at a time in the order
4447
/// they were received. This ensures sequential processing of background tasks.
4548
///
46-
/// The queue is cloneable (`Arc`-based internally), allowing multiple producers
47-
/// to submit tasks concurrently.
49+
/// The queue runs within our single-threaded runtime but maintains compatibility
50+
/// with the Send+Sync requirements of the LSP. This provides the benefits of
51+
/// simpler execution while maintaining the required trait bounds.
4852
///
4953
/// Shutdown is handled gracefully when the last `Queue` instance is dropped.
5054
#[derive(Clone)]

crates/djls-server/src/session.rs

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ pub struct Session {
1919
/// where we're using the `StorageHandle` to create a thread-safe handle that can be
2020
/// shared between threads. When we need to use it, we clone the handle to get a new reference.
2121
///
22+
/// This handle allows us to create database instances as needed.
23+
/// Even though we're using a single-threaded runtime, we still need
24+
/// this to be thread-safe because of LSP trait requirements.
25+
///
2226
/// Usage:
2327
/// ```rust,ignore
2428
/// // Use the StorageHandle in Session
@@ -41,20 +45,6 @@ pub struct Session {
4145
}
4246

4347
impl Session {
44-
pub fn new(client_capabilities: ClientCapabilities) -> Self {
45-
Self {
46-
client_capabilities: Some(client_capabilities),
47-
project: None,
48-
documents: Store::new(),
49-
settings: Settings::default(),
50-
db_handle: StorageHandle::new(None),
51-
}
52-
}
53-
54-
pub fn client_capabilities(&self) -> Option<&ClientCapabilities> {
55-
self.client_capabilities.as_ref()
56-
}
57-
5848
pub fn client_capabilities_mut(&mut self) -> &mut Option<ClientCapabilities> {
5949
&mut self.client_capabilities
6050
}
@@ -83,14 +73,6 @@ impl Session {
8373
&mut self.settings
8474
}
8575

86-
/// Get the raw database handle from the session
87-
///
88-
/// Note: In most cases, you'll want to use `db()` instead to get a usable
89-
/// database instance directly.
90-
pub fn db_handle(&self) -> &StorageHandle<ServerDatabase> {
91-
&self.db_handle
92-
}
93-
9476
/// Get a database instance directly from the session
9577
///
9678
/// This creates a usable database from the handle, which can be used

crates/djls-templates/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ edition = "2021"
55

66
[dependencies]
77
anyhow = { workspace = true }
8-
tower-lsp-server = { workspace = true }
98
serde = { workspace = true }
109
thiserror = { workspace = true }
1110
toml = "0.8"

crates/djls-templates/src/error.rs

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use serde::Serialize;
22
use thiserror::Error;
3-
use tower_lsp_server::lsp_types;
43

54
use crate::ast::AstError;
65
use crate::ast::Span;
@@ -52,17 +51,6 @@ impl TemplateError {
5251
}
5352
}
5453

55-
#[must_use]
56-
pub fn severity(&self) -> lsp_types::DiagnosticSeverity {
57-
match self {
58-
TemplateError::Lexer(_) | TemplateError::Parser(_) => {
59-
lsp_types::DiagnosticSeverity::ERROR
60-
}
61-
TemplateError::Validation(_) => lsp_types::DiagnosticSeverity::WARNING,
62-
_ => lsp_types::DiagnosticSeverity::INFORMATION,
63-
}
64-
}
65-
6654
#[must_use]
6755
pub fn code(&self) -> &'static str {
6856
match self {
@@ -75,26 +63,6 @@ impl TemplateError {
7563
}
7664
}
7765

78-
pub fn to_lsp_diagnostic(error: &TemplateError, _source: &str) -> lsp_types::Diagnostic {
79-
let range = error.span().map_or_else(lsp_types::Range::default, |span| {
80-
let start = lsp_types::Position::new(0, span.start());
81-
let end = lsp_types::Position::new(0, span.start() + span.length());
82-
lsp_types::Range::new(start, end)
83-
});
84-
85-
lsp_types::Diagnostic {
86-
range,
87-
severity: Some(error.severity()),
88-
code: Some(lsp_types::NumberOrString::String(error.code().to_string())),
89-
code_description: None,
90-
source: Some("djls-template".to_string()),
91-
message: error.to_string(),
92-
related_information: None,
93-
tags: None,
94-
data: None,
95-
}
96-
}
97-
9866
pub struct QuickFix {
9967
pub title: String,
10068
pub edit: String,

crates/djls-templates/src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ mod tagspecs;
66
mod tokens;
77

88
use ast::Ast;
9-
pub use error::to_lsp_diagnostic;
109
pub use error::QuickFix;
1110
pub use error::TemplateError;
1211
use lexer::Lexer;

0 commit comments

Comments
 (0)