@@ -7,14 +7,54 @@ use crate::config::DepsConfig;
77use crate :: document:: { DocumentState , ServerState } ;
88use crate :: handlers:: diagnostics;
99use deps_core:: Ecosystem ;
10+ use deps_core:: Registry ;
1011use deps_core:: Result ;
12+ use futures:: future:: join_all;
1113use std:: collections:: HashMap ;
1214use std:: sync:: Arc ;
1315use tokio:: sync:: RwLock ;
1416use tokio:: task:: JoinHandle ;
1517use tower_lsp:: Client ;
1618use tower_lsp:: lsp_types:: Url ;
1719
20+ /// Fetches latest versions for multiple packages in parallel.
21+ ///
22+ /// Returns a HashMap mapping package names to their latest version strings.
23+ /// Packages that fail to fetch are omitted from the result.
24+ ///
25+ /// This function executes all registry requests concurrently, reducing
26+ /// total fetch time from O(N × network_latency) to O(max(network_latency)).
27+ ///
28+ /// # Examples
29+ ///
30+ /// With 50 dependencies and 100ms per request:
31+ /// - Sequential: 50 × 100ms = 5000ms
32+ /// - Parallel: max(100ms) ≈ 150ms
33+ async fn fetch_latest_versions_parallel (
34+ registry : Arc < dyn Registry > ,
35+ package_names : Vec < String > ,
36+ ) -> HashMap < String , String > {
37+ let futures: Vec < _ > = package_names
38+ . into_iter ( )
39+ . map ( |name| {
40+ let registry = Arc :: clone ( & registry) ;
41+ async move {
42+ registry
43+ . get_versions ( & name)
44+ . await
45+ . ok ( )
46+ . and_then ( |versions| {
47+ versions
48+ . first ( )
49+ . map ( |v| ( name, v. version_string ( ) . to_string ( ) ) )
50+ } )
51+ }
52+ } )
53+ . collect ( ) ;
54+
55+ join_all ( futures) . await . into_iter ( ) . flatten ( ) . collect ( )
56+ }
57+
1858/// Generic document open handler using ecosystem registry.
1959///
2060/// Parses manifest using the ecosystem's parser, creates document state,
@@ -72,7 +112,7 @@ pub async fn handle_document_open(
72112 doc. update_cached_versions ( resolved_versions. clone ( ) ) ;
73113 }
74114
75- let doc = match state_clone. get_document ( & uri_clone) {
115+ let doc = match state_clone. get_document_clone ( & uri_clone) {
76116 Some ( d) => d,
77117 None => return ,
78118 } ;
@@ -89,19 +129,9 @@ pub async fn handle_document_open(
89129 . map ( |d| d. name ( ) . to_string ( ) )
90130 . collect ( ) ;
91131
92- drop ( doc) ; // Release guard before async operations
93-
94- // Fetch latest versions from registry (for update hints)
132+ // Fetch latest versions from registry in parallel (for update hints)
95133 let registry = ecosystem_clone. registry ( ) ;
96- let mut cached_versions = HashMap :: new ( ) ;
97-
98- for name in dep_names {
99- if let Ok ( versions) = registry. get_versions ( & name) . await
100- && let Some ( latest) = versions. first ( )
101- {
102- cached_versions. insert ( name, latest. version_string ( ) . to_string ( ) ) ;
103- }
104- }
134+ let cached_versions = fetch_latest_versions_parallel ( registry, dep_names) . await ;
105135
106136 // Update document state with cached versions (latest from registry)
107137 if let Some ( mut doc) = state_clone. documents . get_mut ( & uri_clone) {
@@ -184,7 +214,7 @@ pub async fn handle_document_change(
184214 doc. update_cached_versions ( resolved_versions. clone ( ) ) ;
185215 }
186216
187- let doc = match state_clone. get_document ( & uri_clone) {
217+ let doc = match state_clone. get_document_clone ( & uri_clone) {
188218 Some ( d) => d,
189219 None => return ,
190220 } ;
@@ -201,19 +231,9 @@ pub async fn handle_document_change(
201231 . map ( |d| d. name ( ) . to_string ( ) )
202232 . collect ( ) ;
203233
204- drop ( doc) ;
205-
206- // Fetch latest versions from registry (for update hints)
234+ // Fetch latest versions from registry in parallel (for update hints)
207235 let registry = ecosystem_clone. registry ( ) ;
208- let mut cached_versions = HashMap :: new ( ) ;
209-
210- for name in dep_names {
211- if let Ok ( versions) = registry. get_versions ( & name) . await
212- && let Some ( latest) = versions. first ( )
213- {
214- cached_versions. insert ( name, latest. version_string ( ) . to_string ( ) ) ;
215- }
216- }
236+ let cached_versions = fetch_latest_versions_parallel ( registry, dep_names) . await ;
217237
218238 // Update document state with cached versions (latest from registry)
219239 if let Some ( mut doc) = state_clone. documents . get_mut ( & uri_clone) {
0 commit comments