Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(npm): cache bust npm specifiers more aggressively #18636

Merged
Merged
Next Next commit
fix(npm): cache bust npm specifiers more aggressively
  • Loading branch information
dsherret committed Apr 8, 2023
commit fecac0d01aac9d75905eaff849fe1157263c4dd8
2 changes: 0 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -311,3 +311,6 @@ opt-level = 3
opt-level = 3
[profile.release.package.base64-simd]
opt-level = 3

[patch.crates-io]
deno_graph = { path = "../deno_graph" }
4 changes: 2 additions & 2 deletions cli/args/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ use std::sync::Arc;

use crate::cache::DenoDir;
use crate::file_fetcher::FileFetcher;
use crate::npm::CliNpmRegistryApi;
use crate::npm::NpmProcessState;
use crate::npm::NpmRegistry;
use crate::util::fs::canonicalize_path_maybe_not_exists;
use crate::version;

Expand Down Expand Up @@ -746,7 +746,7 @@ impl CliOptions {

pub async fn resolve_npm_resolution_snapshot(
&self,
api: &NpmRegistry,
api: &CliNpmRegistryApi,
) -> Result<Option<NpmResolutionSnapshot>, AnyError> {
if let Some(state) = &*NPM_PROCESS_STATE {
// TODO(bartlomieju): remove this clone
Expand Down
2 changes: 1 addition & 1 deletion cli/graph_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ pub async fn build_graph_with_npm_resolution<'a>(
loader: &mut dyn deno_graph::source::Loader,
options: deno_graph::BuildOptions<'a>,
) -> Result<(), AnyError> {
graph.build(roots, loader, options).await;
graph.build(roots.clone(), loader, options).await;

// resolve the dependencies of any pending dependencies
// that were inserted by building the graph
Expand Down
6 changes: 3 additions & 3 deletions cli/lsp/documents.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ use crate::lsp::logging::lsp_warn;
use crate::node;
use crate::node::node_resolve_npm_reference;
use crate::node::NodeResolution;
use crate::npm::CliNpmRegistryApi;
use crate::npm::NpmPackageResolver;
use crate::npm::NpmRegistry;
use crate::npm::NpmResolution;
use crate::npm::PackageJsonDepsInstaller;
use crate::resolver::CliGraphResolver;
Expand Down Expand Up @@ -1166,7 +1166,7 @@ impl Documents {
maybe_import_map: Option<Arc<import_map::ImportMap>>,
maybe_config_file: Option<&ConfigFile>,
maybe_package_json: Option<&PackageJson>,
npm_registry_api: NpmRegistry,
npm_registry_api: CliNpmRegistryApi,
npm_resolution: NpmResolution,
) {
fn calculate_resolver_config_hash(
Expand Down Expand Up @@ -1864,7 +1864,7 @@ console.log(b, "hello deno");

#[test]
fn test_documents_refresh_dependencies_config_change() {
let npm_registry_api = NpmRegistry::new_uninitialized();
let npm_registry_api = CliNpmRegistryApi::new_uninitialized();
let npm_resolution =
NpmResolution::new(npm_registry_api.clone(), None, None);

Expand Down
15 changes: 10 additions & 5 deletions cli/lsp/language_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,9 @@ use crate::graph_util;
use crate::http_util::HttpClient;
use crate::lsp::urls::LspUrlKind;
use crate::npm::create_npm_fs_resolver;
use crate::npm::CliNpmRegistryApi;
use crate::npm::NpmCache;
use crate::npm::NpmPackageResolver;
use crate::npm::NpmRegistry;
use crate::npm::NpmResolution;
use crate::proc_state::ProcState;
use crate::tools::fmt::format_file;
Expand Down Expand Up @@ -145,7 +145,7 @@ pub struct Inner {
/// A lazily create "server" for handling test run requests.
maybe_testing_server: Option<testing::TestServer>,
/// Npm's registry api.
npm_api: NpmRegistry,
npm_api: CliNpmRegistryApi,
/// Npm cache
npm_cache: NpmCache,
/// Npm resolution that is stored in memory.
Expand Down Expand Up @@ -417,8 +417,13 @@ impl LanguageServer {
fn create_lsp_structs(
dir: &DenoDir,
http_client: HttpClient,
) -> (NpmRegistry, NpmCache, NpmPackageResolver, NpmResolution) {
let registry_url = NpmRegistry::default_url();
) -> (
CliNpmRegistryApi,
NpmCache,
NpmPackageResolver,
NpmResolution,
) {
let registry_url = CliNpmRegistryApi::default_url();
let progress_bar = ProgressBar::new(ProgressBarStyle::TextOnly);
let npm_cache = NpmCache::from_deno_dir(
dir,
Expand All @@ -430,7 +435,7 @@ fn create_lsp_structs(
http_client.clone(),
progress_bar.clone(),
);
let api = NpmRegistry::new(
let api = CliNpmRegistryApi::new(
registry_url.clone(),
npm_cache.clone(),
http_client,
Expand Down
6 changes: 3 additions & 3 deletions cli/npm/installer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ use deno_npm::registry::NpmRegistryApi;

use crate::args::package_json::PackageJsonDeps;

use super::NpmRegistry;
use super::CliNpmRegistryApi;
use super::NpmResolution;

#[derive(Debug)]
struct PackageJsonDepsInstallerInner {
has_installed: AtomicBool,
npm_registry_api: NpmRegistry,
npm_registry_api: CliNpmRegistryApi,
npm_resolution: NpmResolution,
package_deps: PackageJsonDeps,
}
Expand All @@ -27,7 +27,7 @@ pub struct PackageJsonDepsInstaller(Option<Arc<PackageJsonDepsInstallerInner>>);

impl PackageJsonDepsInstaller {
pub fn new(
npm_registry_api: NpmRegistry,
npm_registry_api: CliNpmRegistryApi,
npm_resolution: NpmResolution,
deps: Option<PackageJsonDeps>,
) -> Self {
Expand Down
2 changes: 1 addition & 1 deletion cli/npm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ mod tarball;
pub use cache::should_sync_download;
pub use cache::NpmCache;
pub use installer::PackageJsonDepsInstaller;
pub use registry::NpmRegistry;
pub use registry::CliNpmRegistryApi;
pub use resolution::NpmResolution;
pub use resolvers::create_npm_fs_resolver;
pub use resolvers::NpmPackageResolver;
Expand Down
46 changes: 27 additions & 19 deletions cli/npm/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@ static NPM_REGISTRY_DEFAULT_URL: Lazy<Url> = Lazy::new(|| {
});

#[derive(Clone, Debug)]
pub struct NpmRegistry(Option<Arc<NpmRegistryApiInner>>);
pub struct CliNpmRegistryApi(Option<Arc<CliNpmRegistryApiInner>>);

impl NpmRegistry {
impl CliNpmRegistryApi {
pub fn default_url() -> &'static Url {
&NPM_REGISTRY_DEFAULT_URL
}
Expand All @@ -67,7 +67,7 @@ impl NpmRegistry {
http_client: HttpClient,
progress_bar: ProgressBar,
) -> Self {
Self(Some(Arc::new(NpmRegistryApiInner {
Self(Some(Arc::new(CliNpmRegistryApiInner {
base_url,
cache,
force_reload: AtomicBool::new(false),
Expand Down Expand Up @@ -105,14 +105,18 @@ impl NpmRegistry {
///
/// Returns true if it was successfully set for the first time.
pub fn mark_force_reload(&self) -> bool {
// never force reload the registry information if reloading is disabled
if matches!(self.inner().cache.cache_setting(), CacheSetting::Only) {
// never force reload the registry information if reloading
// is disabled or if we're already reloading
if matches!(
self.inner().cache.cache_setting(),
CacheSetting::Only | CacheSetting::ReloadAll
) {
return false;
}
!self.inner().force_reload.swap(true, Ordering::SeqCst)
}

fn inner(&self) -> &Arc<NpmRegistryApiInner> {
fn inner(&self) -> &Arc<CliNpmRegistryApiInner> {
// this panicking indicates a bug in the code where this
// wasn't initialized
self.0.as_ref().unwrap()
Expand All @@ -123,7 +127,7 @@ static SYNC_DOWNLOAD_TASK_QUEUE: Lazy<TaskQueue> =
Lazy::new(TaskQueue::default);

#[async_trait]
impl NpmRegistryApi for NpmRegistry {
impl NpmRegistryApi for CliNpmRegistryApi {
async fn package_info(
&self,
name: &str,
Expand All @@ -148,16 +152,17 @@ impl NpmRegistryApi for NpmRegistry {
}
}

type CacheItemPendingResult =
Result<Option<Arc<NpmPackageInfo>>, Arc<AnyError>>;

#[derive(Debug)]
enum CacheItem {
Pending(
Shared<BoxFuture<'static, Result<Option<Arc<NpmPackageInfo>>, String>>>,
),
Pending(Shared<BoxFuture<'static, CacheItemPendingResult>>),
Resolved(Option<Arc<NpmPackageInfo>>),
}

#[derive(Debug)]
struct NpmRegistryApiInner {
struct CliNpmRegistryApiInner {
base_url: Url,
cache: NpmCache,
force_reload: AtomicBool,
Expand All @@ -167,7 +172,7 @@ struct NpmRegistryApiInner {
progress_bar: ProgressBar,
}

impl NpmRegistryApiInner {
impl CliNpmRegistryApiInner {
pub async fn maybe_package_info(
self: &Arc<Self>,
name: &str,
Expand Down Expand Up @@ -197,9 +202,15 @@ impl NpmRegistryApiInner {
let future = {
let api = self.clone();
let name = name.to_string();
async move { api.load_package_info_from_registry(&name).await }
.boxed()
.shared()
async move {
api
.load_package_info_from_registry(&name)
.await
.map(|info| info.map(Arc::new))
.map_err(Arc::new)
}
.boxed()
.shared()
};
mem_cache
.insert(name.to_string(), CacheItem::Pending(future.clone()));
Expand Down Expand Up @@ -304,7 +315,7 @@ impl NpmRegistryApiInner {
async fn load_package_info_from_registry(
&self,
name: &str,
) -> Result<Option<Arc<NpmPackageInfo>>, String> {
) -> Result<Option<NpmPackageInfo>, AnyError> {
self
.load_package_info_from_registry_inner(name)
.await
Expand All @@ -315,9 +326,6 @@ impl NpmRegistryApiInner {
name
)
})
.map(|info| info.map(Arc::new))
// make cloneable
.map_err(|err| format!("{err:#}"))
}

async fn load_package_info_from_registry_inner(
Expand Down
8 changes: 4 additions & 4 deletions cli/npm/resolution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use deno_semver::npm::NpmPackageReqReference;

use crate::args::Lockfile;

use super::registry::NpmRegistry;
use super::registry::CliNpmRegistryApi;

/// Handles updating and storing npm resolution in memory where the underlying
/// snapshot can be updated concurrently. Additionally handles updating the lockfile
Expand All @@ -38,7 +38,7 @@ use super::registry::NpmRegistry;
pub struct NpmResolution(Arc<NpmResolutionInner>);

struct NpmResolutionInner {
api: NpmRegistry,
api: CliNpmRegistryApi,
snapshot: RwLock<NpmResolutionSnapshot>,
update_queue: TaskQueue,
maybe_lockfile: Option<Arc<Mutex<Lockfile>>>,
Expand All @@ -55,7 +55,7 @@ impl std::fmt::Debug for NpmResolution {

impl NpmResolution {
pub fn new(
api: NpmRegistry,
api: CliNpmRegistryApi,
initial_snapshot: Option<NpmResolutionSnapshot>,
maybe_lockfile: Option<Arc<Mutex<Lockfile>>>,
) -> Self {
Expand Down Expand Up @@ -247,7 +247,7 @@ impl NpmResolution {
}

async fn add_package_reqs_to_snapshot(
api: &NpmRegistry,
api: &CliNpmRegistryApi,
// todo(18079): it should be possible to pass &[NpmPackageReq] in here
// and avoid all these clones, but the LSP complains because of its
// `Send` requirement
Expand Down
8 changes: 4 additions & 4 deletions cli/proc_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ use crate::http_util::HttpClient;
use crate::node;
use crate::node::NodeResolution;
use crate::npm::create_npm_fs_resolver;
use crate::npm::CliNpmRegistryApi;
use crate::npm::NpmCache;
use crate::npm::NpmPackageResolver;
use crate::npm::NpmRegistry;
use crate::npm::NpmResolution;
use crate::npm::PackageJsonDepsInstaller;
use crate::resolver::CliGraphResolver;
Expand Down Expand Up @@ -95,7 +95,7 @@ pub struct Inner {
pub resolver: Arc<CliGraphResolver>,
maybe_file_watcher_reporter: Option<FileWatcherReporter>,
pub node_analysis_cache: NodeAnalysisCache,
pub npm_api: NpmRegistry,
pub npm_api: CliNpmRegistryApi,
pub npm_cache: NpmCache,
pub npm_resolver: NpmPackageResolver,
pub npm_resolution: NpmResolution,
Expand Down Expand Up @@ -233,14 +233,14 @@ impl ProcState {

let lockfile = cli_options.maybe_lock_file();

let npm_registry_url = NpmRegistry::default_url().to_owned();
let npm_registry_url = CliNpmRegistryApi::default_url().to_owned();
let npm_cache = NpmCache::from_deno_dir(
&dir,
cli_options.cache_setting(),
http_client.clone(),
progress_bar.clone(),
);
let npm_api = NpmRegistry::new(
let npm_api = CliNpmRegistryApi::new(
npm_registry_url.clone(),
npm_cache.clone(),
http_client.clone(),
Expand Down
Loading