1
1
mod dependency_manager;
2
2
3
3
use std:: {
4
- cell:: RefCell ,
5
- collections:: { HashMap , HashSet } ,
6
- process:: Command ,
7
- rc:: Rc ,
8
- time:: Instant ,
4
+ cell:: RefCell , collections:: { HashMap , HashSet } , io:: Read , process:: Command , rc:: Rc , time:: Instant
9
5
} ;
10
6
11
7
use camino:: { Utf8Path , Utf8PathBuf } ;
12
8
use ecow:: { EcoString , eco_format} ;
13
9
use flate2:: read:: GzDecoder ;
14
10
use gleam_core:: {
15
- Error , Result ,
16
11
build:: { Mode , Target , Telemetry } ,
17
12
config:: PackageConfig ,
18
13
dependency:: { self , PackageFetchError } ,
@@ -22,6 +17,9 @@ use gleam_core::{
22
17
manifest:: { Base16Checksum , Manifest , ManifestPackage , ManifestPackageSource , Resolved } ,
23
18
paths:: ProjectPaths ,
24
19
requirement:: Requirement ,
20
+ io:: { FileSystemReader , FileSystemWriter , HttpClient as _, } ,
21
+ paths:: { global_hexpm_package_release_response_cache, global_hexpm_packages_response_cache} ,
22
+ Error , Result
25
23
} ;
26
24
use hexpm:: version:: Version ;
27
25
use itertools:: Itertools ;
@@ -34,11 +32,7 @@ pub use dependency_manager::DependencyManagerConfig;
34
32
mod tests;
35
33
36
34
use crate :: {
37
- TreeOptions ,
38
- build_lock:: { BuildLock , Guard } ,
39
- cli,
40
- fs:: { self , ProjectIO } ,
41
- http:: HttpClient ,
35
+ build_lock:: { BuildLock , Guard } , cli, fs:: { self , ProjectIO } , http:: HttpClient , TreeOptions
42
36
} ;
43
37
44
38
struct Symbols {
@@ -1093,8 +1087,37 @@ async fn lookup_package(
1093
1087
Some ( provided_package) => Ok ( provided_package. to_manifest_package ( name. as_str ( ) ) ) ,
1094
1088
None => {
1095
1089
let config = hexpm:: Config :: new ( ) ;
1090
+ // performance may be able to be improved by reading from local cache first
1091
+ // depending on the volatility of the endpoint
1092
+ // retirement status volatile, content volatile one hour after initial publication
1093
+ // content may be edited or deleted by admins
1094
+ let mut resp_body = Vec :: new ( ) ;
1096
1095
let release =
1097
- hex:: get_package_release ( & name, & version, & config, & HttpClient :: new ( ) ) . await ?;
1096
+ hex:: get_package_release ( & name, & version, & config, Some ( & mut resp_body) , & HttpClient :: new ( ) ) . await ;
1097
+ let fs = ProjectIO :: new ( ) ;
1098
+ let cache_path = global_hexpm_package_release_response_cache ( & name, & version. to_string ( ) ) ;
1099
+ let release = match release {
1100
+ Ok ( rel) => {
1101
+ // save
1102
+ // FIXME: I may not need to wright every time
1103
+ let _ = fs. write_bytes ( & cache_path, & resp_body) ;
1104
+ rel
1105
+ } ,
1106
+ Err ( _) => {
1107
+ // load
1108
+ let cached_result = fs. read_bytes ( & cache_path)
1109
+ . map_err ( |err| Error :: FileIo {
1110
+ action : FileIoAction :: Read ,
1111
+ kind : FileKind :: File ,
1112
+ path : cache_path,
1113
+ err : Some ( err. to_string ( ) ) ,
1114
+ } ) ?;
1115
+
1116
+ // FIXME: I crash when the cache is bad
1117
+ // author note
1118
+ serde_json:: from_slice ( & cached_result) . expect ( "cache bad" )
1119
+ }
1120
+ } ;
1098
1121
let build_tools = release
1099
1122
. meta
1100
1123
. build_tools
@@ -1187,10 +1210,28 @@ impl dependency::PackageFetcher for PackageFetcher {
1187
1210
let response = self
1188
1211
. runtime
1189
1212
. block_on ( self . http . send ( request) )
1190
- . map_err ( PackageFetchError :: fetch_error) ?;
1213
+ . map_err ( PackageFetchError :: fetch_error) ;
1214
+
1215
+ let fs = ProjectIO :: new ( ) ;
1216
+ let cache_path = & global_hexpm_packages_response_cache ( package) ;
1217
+ let pkg = match response {
1218
+ Ok ( resp) => {
1219
+ tracing:: debug!( package = package, "saving_hex_package" ) ;
1220
+ let _ = fs. write_bytes ( cache_path, resp. body ( ) ) ;
1221
+ hexpm:: get_package_response ( resp, HEXPM_PUBLIC_KEY )
1222
+ } ,
1223
+ Err ( _err) => {
1224
+ tracing:: debug!( package = package, "fetching_package_data_from_cache" ) ;
1225
+ let reader = fs. reader ( cache_path)
1226
+ . map_err ( PackageFetchError :: fetch_error) ?;
1227
+ let mut decoder = GzDecoder :: new ( reader) ;
1228
+ let mut data = Vec :: new ( ) ;
1229
+ let _ = decoder. read_to_end ( & mut data)
1230
+ . map_err ( PackageFetchError :: fetch_error) ?;
1231
+ hexpm:: get_package_data ( & data, HEXPM_PUBLIC_KEY )
1232
+ } ,
1233
+ } . map_err ( PackageFetchError :: from) ?;
1191
1234
1192
- let pkg = hexpm:: get_package_response ( response, HEXPM_PUBLIC_KEY )
1193
- . map_err ( PackageFetchError :: from) ?;
1194
1235
let pkg = Rc :: new ( pkg) ;
1195
1236
let pkg_ref = Rc :: clone ( & pkg) ;
1196
1237
self . cache_package ( package, pkg) ;
0 commit comments