Skip to content

Commit 4fab252

Browse files
dsherretlucacasonato
authored andcommitted
fix(npm): cache bust npm specifiers more aggressively (#18636)
Part 1: #18622 Part 2: This PR Closes #16901 --------- Co-authored-by: Luca Casonato <[email protected]>
1 parent b183737 commit 4fab252

File tree

14 files changed

+291
-145
lines changed

14 files changed

+291
-145
lines changed

Cargo.lock

Lines changed: 8 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cli/Cargo.toml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@ winres.workspace = true
4242
[dependencies]
4343
deno_ast = { workspace = true, features = ["bundler", "cjs", "codegen", "dep_graph", "module_specifier", "proposal", "react", "sourcemap", "transforms", "typescript", "view", "visit"] }
4444
deno_core = { workspace = true, features = ["include_js_files_for_snapshotting"] }
45-
deno_doc = "0.60.0"
46-
deno_emit = "0.18.0"
47-
deno_graph = "=0.46.0"
45+
deno_doc = "0.61.0"
46+
deno_emit = "0.19.0"
47+
deno_graph = "=0.47.1"
4848
deno_lint = { version = "0.43.0", features = ["docs"] }
4949
deno_lockfile.workspace = true
5050
deno_npm = "0.2.0"
@@ -70,7 +70,7 @@ dprint-plugin-markdown = "=0.15.2"
7070
dprint-plugin-typescript = "=0.84.0"
7171
encoding_rs.workspace = true
7272
env_logger = "=0.9.0"
73-
eszip = "=0.39.0"
73+
eszip = "=0.40.0"
7474
fancy-regex = "=0.10.0"
7575
flate2.workspace = true
7676
fs3.workspace = true

cli/args/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ use std::sync::Arc;
6464

6565
use crate::cache::DenoDir;
6666
use crate::file_fetcher::FileFetcher;
67+
use crate::npm::CliNpmRegistryApi;
6768
use crate::npm::NpmProcessState;
68-
use crate::npm::NpmRegistry;
6969
use crate::util::fs::canonicalize_path_maybe_not_exists;
7070
use crate::version;
7171

@@ -744,7 +744,7 @@ impl CliOptions {
744744

745745
pub async fn resolve_npm_resolution_snapshot(
746746
&self,
747-
api: &NpmRegistry,
747+
api: &CliNpmRegistryApi,
748748
) -> Result<Option<NpmResolutionSnapshot>, AnyError> {
749749
if let Some(state) = &*NPM_PROCESS_STATE {
750750
// TODO(bartlomieju): remove this clone

cli/lsp/documents.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ use crate::lsp::logging::lsp_warn;
2020
use crate::node;
2121
use crate::node::node_resolve_npm_reference;
2222
use crate::node::NodeResolution;
23+
use crate::npm::CliNpmRegistryApi;
2324
use crate::npm::NpmPackageResolver;
24-
use crate::npm::NpmRegistry;
2525
use crate::npm::NpmResolution;
2626
use crate::npm::PackageJsonDepsInstaller;
2727
use crate::resolver::CliGraphResolver;
@@ -1166,7 +1166,7 @@ impl Documents {
11661166
maybe_import_map: Option<Arc<import_map::ImportMap>>,
11671167
maybe_config_file: Option<&ConfigFile>,
11681168
maybe_package_json: Option<&PackageJson>,
1169-
npm_registry_api: NpmRegistry,
1169+
npm_registry_api: CliNpmRegistryApi,
11701170
npm_resolution: NpmResolution,
11711171
) {
11721172
fn calculate_resolver_config_hash(
@@ -1864,7 +1864,7 @@ console.log(b, "hello deno");
18641864

18651865
#[test]
18661866
fn test_documents_refresh_dependencies_config_change() {
1867-
let npm_registry_api = NpmRegistry::new_uninitialized();
1867+
let npm_registry_api = CliNpmRegistryApi::new_uninitialized();
18681868
let npm_resolution =
18691869
NpmResolution::new(npm_registry_api.clone(), None, None);
18701870

cli/lsp/language_server.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,9 @@ use crate::graph_util;
7979
use crate::http_util::HttpClient;
8080
use crate::lsp::urls::LspUrlKind;
8181
use crate::npm::create_npm_fs_resolver;
82+
use crate::npm::CliNpmRegistryApi;
8283
use crate::npm::NpmCache;
8384
use crate::npm::NpmPackageResolver;
84-
use crate::npm::NpmRegistry;
8585
use crate::npm::NpmResolution;
8686
use crate::proc_state::ProcState;
8787
use crate::tools::fmt::format_file;
@@ -145,7 +145,7 @@ pub struct Inner {
145145
/// A lazily create "server" for handling test run requests.
146146
maybe_testing_server: Option<testing::TestServer>,
147147
/// Npm's registry api.
148-
npm_api: NpmRegistry,
148+
npm_api: CliNpmRegistryApi,
149149
/// Npm cache
150150
npm_cache: NpmCache,
151151
/// Npm resolution that is stored in memory.
@@ -417,8 +417,13 @@ impl LanguageServer {
417417
fn create_lsp_structs(
418418
dir: &DenoDir,
419419
http_client: HttpClient,
420-
) -> (NpmRegistry, NpmCache, NpmPackageResolver, NpmResolution) {
421-
let registry_url = NpmRegistry::default_url();
420+
) -> (
421+
CliNpmRegistryApi,
422+
NpmCache,
423+
NpmPackageResolver,
424+
NpmResolution,
425+
) {
426+
let registry_url = CliNpmRegistryApi::default_url();
422427
let progress_bar = ProgressBar::new(ProgressBarStyle::TextOnly);
423428
let npm_cache = NpmCache::from_deno_dir(
424429
dir,
@@ -430,7 +435,7 @@ fn create_lsp_structs(
430435
http_client.clone(),
431436
progress_bar.clone(),
432437
);
433-
let api = NpmRegistry::new(
438+
let api = CliNpmRegistryApi::new(
434439
registry_url.clone(),
435440
npm_cache.clone(),
436441
http_client,

cli/npm/installer.rs

Lines changed: 53 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,69 @@
11
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
22

3+
use std::future::Future;
34
use std::sync::Arc;
45

56
use deno_core::error::AnyError;
67
use deno_core::futures::stream::FuturesOrdered;
78
use deno_core::futures::StreamExt;
89
use deno_npm::registry::NpmRegistryApi;
10+
use deno_npm::registry::NpmRegistryPackageInfoLoadError;
11+
use deno_semver::npm::NpmPackageReq;
912

1013
use crate::args::package_json::PackageJsonDeps;
1114
use crate::util::sync::AtomicFlag;
1215

13-
use super::NpmRegistry;
16+
use super::CliNpmRegistryApi;
1417
use super::NpmResolution;
1518

1619
#[derive(Debug)]
1720
struct PackageJsonDepsInstallerInner {
1821
has_installed_flag: AtomicFlag,
19-
npm_registry_api: NpmRegistry,
22+
npm_registry_api: CliNpmRegistryApi,
2023
npm_resolution: NpmResolution,
2124
package_deps: PackageJsonDeps,
2225
}
2326

27+
impl PackageJsonDepsInstallerInner {
28+
pub fn reqs(&self) -> Vec<&NpmPackageReq> {
29+
let mut package_reqs = self
30+
.package_deps
31+
.values()
32+
.filter_map(|r| r.as_ref().ok())
33+
.collect::<Vec<_>>();
34+
package_reqs.sort(); // deterministic resolution
35+
package_reqs
36+
}
37+
38+
pub fn reqs_with_info_futures(
39+
&self,
40+
) -> FuturesOrdered<
41+
impl Future<
42+
Output = Result<
43+
(&NpmPackageReq, Arc<deno_npm::registry::NpmPackageInfo>),
44+
NpmRegistryPackageInfoLoadError,
45+
>,
46+
>,
47+
> {
48+
let package_reqs = self.reqs();
49+
50+
FuturesOrdered::from_iter(package_reqs.into_iter().map(|req| {
51+
let api = self.npm_registry_api.clone();
52+
async move {
53+
let info = api.package_info(&req.name).await?;
54+
Ok::<_, NpmRegistryPackageInfoLoadError>((req, info))
55+
}
56+
}))
57+
}
58+
}
59+
2460
/// Holds and controls installing dependencies from package.json.
2561
#[derive(Debug, Clone, Default)]
2662
pub struct PackageJsonDepsInstaller(Option<Arc<PackageJsonDepsInstallerInner>>);
2763

2864
impl PackageJsonDepsInstaller {
2965
pub fn new(
30-
npm_registry_api: NpmRegistry,
66+
npm_registry_api: CliNpmRegistryApi,
3167
npm_resolution: NpmResolution,
3268
deps: Option<PackageJsonDeps>,
3369
) -> Self {
@@ -57,27 +93,23 @@ impl PackageJsonDepsInstaller {
5793
return Ok(()); // already installed by something else
5894
}
5995

60-
let mut package_reqs = inner
61-
.package_deps
62-
.values()
63-
.filter_map(|r| r.as_ref().ok())
64-
.collect::<Vec<_>>();
65-
package_reqs.sort(); // deterministic resolution
66-
67-
let mut req_with_infos =
68-
FuturesOrdered::from_iter(package_reqs.into_iter().map(|req| {
69-
let api = inner.npm_registry_api.clone();
70-
async move {
71-
let info = api.package_info(&req.name).await?;
72-
Ok::<_, AnyError>((req, info))
73-
}
74-
}));
96+
let mut reqs_with_info_futures = inner.reqs_with_info_futures();
7597

76-
while let Some(result) = req_with_infos.next().await {
98+
while let Some(result) = reqs_with_info_futures.next().await {
7799
let (req, info) = result?;
78-
inner
100+
let result = inner
79101
.npm_resolution
80-
.resolve_package_req_as_pending_with_info(req, &info)?;
102+
.resolve_package_req_as_pending_with_info(req, &info);
103+
if let Err(err) = result {
104+
if inner.npm_registry_api.mark_force_reload() {
105+
log::debug!("Failed to resolve package. Retrying. Error: {err:#}");
106+
// re-initialize
107+
inner.npm_registry_api.clear_memory_cache();
108+
reqs_with_info_futures = inner.reqs_with_info_futures();
109+
} else {
110+
return Err(err.into());
111+
}
112+
}
81113
}
82114

83115
Ok(())

cli/npm/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ mod tarball;
1010
pub use cache::should_sync_download;
1111
pub use cache::NpmCache;
1212
pub use installer::PackageJsonDepsInstaller;
13-
pub use registry::NpmRegistry;
13+
pub use registry::CliNpmRegistryApi;
1414
pub use resolution::NpmResolution;
1515
pub use resolvers::create_npm_fs_resolver;
1616
pub use resolvers::NpmPackageResolver;

0 commit comments

Comments
 (0)