@@ -2,19 +2,32 @@ use crate::build::packages;
2
2
use crate :: config:: Config ;
3
3
use crate :: helpers;
4
4
use crate :: project_context:: ProjectContext ;
5
+ use ahash:: AHashMap ;
5
6
use anyhow:: anyhow;
6
7
use std:: ffi:: OsString ;
7
8
use std:: fs;
8
9
use std:: fs:: File ;
9
10
use std:: io:: Read ;
10
11
use std:: io:: { self , BufRead } ;
11
12
use std:: path:: { Component , Path , PathBuf } ;
13
+ use std:: sync:: { LazyLock , RwLock } ;
12
14
use std:: time:: { SystemTime , UNIX_EPOCH } ;
13
15
14
16
pub type StdErr = String ;
15
17
16
18
pub mod deserialize;
17
19
20
+ // Thread-safe memoization cache for try_package_path results per build.
21
+ // Keyed by "{package_config.name}+{package_name}". Value is Some(path) or None (not found).
22
+ static TRY_PACKAGE_PATH_CACHE : LazyLock < RwLock < AHashMap < String , Option < PathBuf > > > > =
23
+ LazyLock :: new ( || RwLock :: new ( AHashMap :: new ( ) ) ) ;
24
+
25
+ pub fn reset_try_package_path_cache ( ) {
26
+ if let Ok ( mut map) = TRY_PACKAGE_PATH_CACHE . write ( ) {
27
+ map. clear ( ) ;
28
+ }
29
+ }
30
+
18
31
pub mod emojis {
19
32
use console:: Emoji ;
20
33
pub static COMMAND : Emoji < ' _ , ' _ > = Emoji ( "🏃 " , "" ) ;
@@ -114,6 +127,19 @@ pub fn try_package_path(
114
127
project_context : & ProjectContext ,
115
128
package_name : & str ,
116
129
) -> anyhow:: Result < PathBuf > {
130
+ // First, attempt to serve from cache
131
+ let cache_key = format ! ( "{}+{}" , package_config. name, package_name) ;
132
+ if let Ok ( cache) = TRY_PACKAGE_PATH_CACHE . read ( ) {
133
+ if let Some ( cached) = cache. get ( & cache_key) {
134
+ return match cached {
135
+ Some ( path) => Ok ( path. clone ( ) ) ,
136
+ None => Err ( anyhow ! (
137
+ "The package \" {package_name}\" is not found (are node_modules up-to-date?)..."
138
+ ) ) ,
139
+ } ;
140
+ }
141
+ }
142
+
117
143
// package folder + node_modules + package_name
118
144
// This can happen in the following scenario:
119
145
// The ProjectContext has a MonoRepoContext::MonorepoRoot.
@@ -147,7 +173,7 @@ pub fn try_package_path(
147
173
148
174
// root folder + node_modules + package_name
149
175
let path_from_root = package_path ( project_context. get_root_path ( ) , package_name) ;
150
- if path_from_current_package. exists ( ) {
176
+ let result = if path_from_current_package. exists ( ) {
151
177
Ok ( path_from_current_package)
152
178
} else if path_from_current_config. exists ( ) {
153
179
Ok ( path_from_current_config)
@@ -157,7 +183,21 @@ pub fn try_package_path(
157
183
Err ( anyhow ! (
158
184
"The package \" {package_name}\" is not found (are node_modules up-to-date?)..."
159
185
) )
186
+ } ;
187
+
188
+ // Store in cache
189
+ if let Ok ( mut cache) = TRY_PACKAGE_PATH_CACHE . write ( ) {
190
+ match & result {
191
+ Ok ( path) => {
192
+ cache. insert ( cache_key, Some ( path. clone ( ) ) ) ;
193
+ }
194
+ Err ( _) => {
195
+ cache. insert ( cache_key, None ) ;
196
+ }
197
+ }
160
198
}
199
+
200
+ result
161
201
}
162
202
163
203
pub fn get_abs_path ( path : & Path ) -> PathBuf {
0 commit comments