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

feat: hashmap based caching #82

Merged
merged 80 commits into from Aug 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
7f32245
refactor: naming convention
KSXGitHub Aug 15, 2023
785e878
refactor: remove useless task spawn
KSXGitHub Aug 15, 2023
54b7cc1
feat: panic on invalid UTF-8
KSXGitHub Aug 15, 2023
f35fdff
refactor: remove unnecessary copy and allocation
KSXGitHub Aug 15, 2023
fe0583d
docs: add a TODO
KSXGitHub Aug 15, 2023
3b600d9
refactor: remove node_modules_path
KSXGitHub Aug 15, 2023
5301577
feat: hashmap caching communication
KSXGitHub Aug 15, 2023
cbfe18c
feat: log cache hit
KSXGitHub Aug 15, 2023
e83c4c0
chore: merge from main
KSXGitHub Aug 15, 2023
ed708b1
feat: use tracing library
KSXGitHub Aug 15, 2023
0fe3e95
feat: propagate archive error
KSXGitHub Aug 15, 2023
f7b32cd
docs: change the TODO
KSXGitHub Aug 15, 2023
7bcaf06
refactor: rename cache state
KSXGitHub Aug 15, 2023
4d1b724
feat: remove unused function
KSXGitHub Aug 15, 2023
2103470
docs: ask a question
KSXGitHub Aug 15, 2023
85dc278
feat: import on cache hit
KSXGitHub Aug 15, 2023
ca7de84
feat: log saved_path
KSXGitHub Aug 15, 2023
d06fd00
feat: log cache miss
KSXGitHub Aug 15, 2023
a23fc50
feat: change tracing level
KSXGitHub Aug 16, 2023
8c4c276
style: consistent string substitution style
KSXGitHub Aug 16, 2023
21a2f89
docs: add a TODO
KSXGitHub Aug 16, 2023
6bd33e9
docs: add a TODO
KSXGitHub Aug 16, 2023
10b8be0
docs: remove poor comment
KSXGitHub Aug 16, 2023
242c189
docs: add a TODO
KSXGitHub Aug 16, 2023
a602dfa
docs: add a TODO
KSXGitHub Aug 16, 2023
cfbac93
feat: fix tracing
KSXGitHub Aug 16, 2023
77adf35
feat: set_panic_hook
KSXGitHub Aug 16, 2023
73d8a9c
refactor: remove unnecessary error variant
KSXGitHub Aug 16, 2023
a70b0ee
refactor: remove unnecessary error variant
KSXGitHub Aug 16, 2023
3b17d25
refactor: rename InProcess to InProgress
KSXGitHub Aug 16, 2023
608c2df
refactor: remove anti-pattern generics
KSXGitHub Aug 17, 2023
7c065e8
refactor: remove anti-pattern generics
KSXGitHub Aug 17, 2023
2ebb0fb
feat: re-add spawn
KSXGitHub Aug 17, 2023
f03439a
docs: add a TODO
KSXGitHub Aug 17, 2023
002efb0
feat: propagate more error
KSXGitHub Aug 17, 2023
6557a7b
feat: propagate more error
KSXGitHub Aug 17, 2023
21280ed
refactor: remove some intermediate variables
KSXGitHub Aug 17, 2023
1bee692
refactor: broadcast is simpler
KSXGitHub Aug 17, 2023
b5470ea
refactor: mpsc is even simpler
KSXGitHub Aug 17, 2023
4fb716a
docs: add a TODO
KSXGitHub Aug 17, 2023
889149a
feat: attach culprit information to error
KSXGitHub Aug 17, 2023
ea40c87
chore: merge from main
KSXGitHub Aug 17, 2023
bddeaa7
feat: attach more information to error
KSXGitHub Aug 18, 2023
a59af39
refactor: replace a PathBuf with &Path
KSXGitHub Aug 18, 2023
9399c70
feat: more resistance to race conditions
KSXGitHub Aug 18, 2023
7bc4943
refactor: change the misleading names
KSXGitHub Aug 18, 2023
2ea6e34
refactor: reduce indentation
KSXGitHub Aug 18, 2023
a2c19c6
fix: the tarball bug
KSXGitHub Aug 18, 2023
9cfa9a1
chore: merge from main
KSXGitHub Aug 18, 2023
74f9dd3
feat: revert previous change
KSXGitHub Aug 18, 2023
aa3dfa2
feat: switch to RwLock
KSXGitHub Aug 18, 2023
e68e3ea
docs: add a TODO
KSXGitHub Aug 19, 2023
480bbba
feat: avoid filling the screen with numbers
KSXGitHub Aug 19, 2023
34b322e
feat: trace install
KSXGitHub Aug 19, 2023
a24137b
feat: trace import
KSXGitHub Aug 20, 2023
bf8cb58
feat: move parsing of integrity out
KSXGitHub Aug 21, 2023
a339c65
feat: correct error message and diagnostic
KSXGitHub Aug 21, 2023
898dee6
feat: propagate parse_integrity_error
KSXGitHub Aug 21, 2023
b846256
feat: remove unnecessary clone
KSXGitHub Aug 21, 2023
2c1eed2
feat: url based caching
KSXGitHub Aug 21, 2023
73388b3
feat: full parallelization
KSXGitHub Aug 21, 2023
8c7db75
feat: skip logging cache
KSXGitHub Aug 21, 2023
c8887ad
feat: log cache.len()
KSXGitHub Aug 21, 2023
479e7e3
feat: log beginning and end of sets and subsets
KSXGitHub Aug 21, 2023
fe32b99
feat: drop lock and sleep
KSXGitHub Aug 22, 2023
9b24ea1
docs: millis
KSXGitHub Aug 22, 2023
80346b6
chore: remove an unused dependency
KSXGitHub Aug 22, 2023
3c380a5
refactor: change var name
KSXGitHub Aug 23, 2023
3c3f4b8
refactor: only compute `save_path` when necessary
KSXGitHub Aug 23, 2023
b921350
docs: remove a TODO
KSXGitHub Aug 23, 2023
fc3e7d0
style: fix string interpolation style
KSXGitHub Aug 23, 2023
104fbcd
docs: move a TODO
KSXGitHub Aug 23, 2023
baa9b82
docs: clarify
KSXGitHub Aug 23, 2023
c736d86
feat: change log message
KSXGitHub Aug 23, 2023
d5eb906
fix: log message grammar
KSXGitHub Aug 23, 2023
90eb4d5
refactor: remove box
KSXGitHub Aug 23, 2023
42422bd
docs: remove the question
KSXGitHub Aug 23, 2023
b76f3a4
feat: reduce panic by using OsString
KSXGitHub Aug 23, 2023
663dd8d
feat: replace `sleep` with `yield_now`
KSXGitHub Aug 23, 2023
c386708
refactor: forgot to reuse `url`
KSXGitHub Aug 23, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
28 changes: 28 additions & 0 deletions Cargo.lock

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

2 changes: 2 additions & 0 deletions Cargo.toml
Expand Up @@ -24,7 +24,9 @@ pacquet_cafs = { path = "crates/cafs" }
pacquet_diagnostics = { path = "crates/diagnostics" }

# Dependencies
async-recursion = { version = "1.0.4" }
clap = { version = "4", features = ["derive", "string"] }
dashmap = { version = "5.5.0" }
home = { version = "0.5.5" }
insta = { version = "1.31.0", features = ["yaml", "glob", "walkdir"] }
futures-util = { version = "0.3.28" }
Expand Down
8 changes: 4 additions & 4 deletions crates/cafs/src/lib.rs
Expand Up @@ -36,11 +36,11 @@ fn content_path_from_hex(file_type: FileType, hex: &str) -> PathBuf {
p.join(format!("{}{}", &hex[2..], extension))
}

pub fn write_sync<P: Into<PathBuf>>(store_dir: P, buffer: &Vec<u8>) -> Result<PathBuf, CafsError> {
pub fn write_sync(store_dir: &Path, buffer: &Vec<u8>) -> Result<PathBuf, CafsError> {
let hex_integrity =
IntegrityOpts::new().algorithm(Algorithm::Sha512).chain(buffer).result().to_hex().1;
let content_path = content_path_from_hex(FileType::NonExec, &hex_integrity);
let file_path = store_dir.into().join(&content_path);
let file_path = store_dir.join(&content_path);

if !file_path.exists() {
let parent_dir = file_path.parent().unwrap();
Expand All @@ -51,10 +51,10 @@ pub fn write_sync<P: Into<PathBuf>>(store_dir: P, buffer: &Vec<u8>) -> Result<Pa
Ok(content_path)
}

pub fn prune_sync<P: Into<PathBuf>>(store_dir: P) -> Result<(), CafsError> {
pub fn prune_sync(store_dir: &Path) -> Result<(), CafsError> {
// TODO: This should remove unreferenced packages, not all packages.
// Ref: https://pnpm.io/cli/store#prune
fs::remove_dir_all(store_dir.into())?;
fs::remove_dir_all(store_dir)?;
Ok(())
}

Expand Down
20 changes: 11 additions & 9 deletions crates/cli/Cargo.toml
Expand Up @@ -23,15 +23,17 @@ pacquet_registry = { workspace = true }
pacquet_tarball = { workspace = true }
pacquet_diagnostics = { workspace = true }

clap = { workspace = true }
futures-util = { workspace = true }
rayon = { workspace = true }
reflink-copy = { workspace = true }
reqwest = { workspace = true }
node-semver = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
tokio = { workspace = true }
async-recursion = { workspace = true }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we using async-recursion? I couldn't find any reference.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#[async_recursion]

clap = { workspace = true }
futures-util = { workspace = true }
rayon = { workspace = true }
reflink-copy = { workspace = true }
reqwest = { workspace = true }
node-semver = { workspace = true }
pipe-trait = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
tokio = { workspace = true }

[dev-dependencies]
insta = { workspace = true }
Expand Down
13 changes: 11 additions & 2 deletions crates/cli/src/commands/add.rs
Expand Up @@ -55,6 +55,7 @@ impl PackageManager {
/// 6. Update package.json
pub async fn add(&mut self, args: &AddCommandArgs) -> Result<(), PackageManagerError> {
let latest_version = fetch_package_version_directly(
&self.tarball_cache,
&self.config,
&self.http_client,
&args.package,
Expand All @@ -72,7 +73,14 @@ impl PackageManager {

let direct_dependency_handles =
latest_version.dependencies(self.config.auto_install_peers).map(|(name, version)| {
find_package_version_from_registry(config, http_client, name, version, path)
find_package_version_from_registry(
&self.tarball_cache,
config,
http_client,
name,
version,
path,
)
});

queue.push_front(future::join_all(direct_dependency_handles).await);
Expand All @@ -90,11 +98,12 @@ impl PackageManager {
let handles = dependency.dependencies(self.config.auto_install_peers).map(
|(name, version)| {
find_package_version_from_registry(
&self.tarball_cache,
config,
http_client,
name,
version,
node_modules_path.to_owned(),
&node_modules_path,
)
},
);
Expand Down
93 changes: 53 additions & 40 deletions crates/cli/src/commands/install.rs
@@ -1,10 +1,12 @@
use crate::package::find_package_version_from_registry;
use crate::package_manager::{PackageManager, PackageManagerError};
use async_recursion::async_recursion;
use clap::Parser;
use futures_util::future;
use pacquet_diagnostics::tracing;
use pacquet_package_json::DependencyGroup;
use pacquet_registry::PackageVersion;
use std::collections::VecDeque;
use pipe_trait::Pipe;

#[derive(Parser, Debug)]
pub struct InstallCommandArgs {
Expand Down Expand Up @@ -40,49 +42,60 @@
}

impl PackageManager {
/// Install dependencies of a dependency.
///
/// This function is used by [`PackageManager::install`].
#[async_recursion]
async fn install_dependencies(&self, package: &PackageVersion) {
let node_modules_path =
self.config.virtual_store_dir.join(package.to_store_name()).join("node_modules");

tracing::info!(target: "pacquet::install", node_modules = ?node_modules_path, "Start subset");

package
.dependencies(self.config.auto_install_peers)
.map(|(name, version)| async {
let dependency = find_package_version_from_registry(
&self.tarball_cache,
&self.config,
&self.http_client,
name,
version,
&node_modules_path,
)
.await
.unwrap();
self.install_dependencies(&dependency).await;
})
.pipe(future::join_all)
.await;

tracing::info!(target: "pacquet::install", node_modules = ?node_modules_path, "Complete subset");
}

/// Jobs of the `install` command.
pub async fn install(&self, args: &InstallCommandArgs) -> Result<(), PackageManagerError> {
let config = &self.config;
let path = &self.config.modules_dir;
let http_client = &self.http_client;
let mut queue: VecDeque<Vec<PackageVersion>> = VecDeque::new();
tracing::info!(target: "pacquet::install", "Start all");

Check warning on line 78 in crates/cli/src/commands/install.rs

View check run for this annotation

Codecov / codecov/patch

crates/cli/src/commands/install.rs#L78

Added line #L78 was not covered by tests

let direct_dependency_handles = self
.package_json
self.package_json
.dependencies(args.dependency_groups())
.map(|(name, version)| async move {
find_package_version_from_registry(config, http_client, name, version, path)
.await
.unwrap()
});

queue.push_front(future::join_all(direct_dependency_handles).await);

while let Some(dependencies) = queue.pop_front() {
for dependency in dependencies {
let node_modules_path = self
.config
.virtual_store_dir
.join(dependency.to_store_name())
.join("node_modules");

let handles = dependency.dependencies(self.config.auto_install_peers).map(
|(name, version)| async {
find_package_version_from_registry(
config,
http_client,
name,
version,
&node_modules_path,
)
.await
.unwrap()
},
);

queue.push_back(future::join_all(handles).await);
}
}

let dependency = find_package_version_from_registry(
&self.tarball_cache,
&self.config,
&self.http_client,
name,
version,
&self.config.modules_dir,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are already passing self.config to this function. We dont need this do we?

)
.await
.unwrap();
self.install_dependencies(&dependency).await;
})
.pipe(future::join_all)
.await;

tracing::info!(target: "pacquet::install", "Complete all");

Check warning on line 98 in crates/cli/src/commands/install.rs

View check run for this annotation

Codecov / codecov/patch

crates/cli/src/commands/install.rs#L98

Added line #L98 was not covered by tests
Ok(())
}
}
Expand Down
4 changes: 2 additions & 2 deletions crates/cli/src/fs.rs
@@ -1,12 +1,12 @@
use std::{io, os, path::Path};

#[cfg(unix)]
pub fn symlink_dir<P: AsRef<Path>>(original: P, link: P) -> io::Result<()> {
pub fn symlink_dir(original: &Path, link: &Path) -> io::Result<()> {
os::unix::fs::symlink(original, link)
}

#[cfg(windows)]
pub fn symlink_dir<P: AsRef<Path>>(original: P, link: P) -> io::Result<()> {
pub fn symlink_dir(original: &Path, link: &Path) -> io::Result<()> {
os::windows::fs::symlink_dir(original, link)
}

Expand Down
3 changes: 2 additions & 1 deletion crates/cli/src/lib.rs
Expand Up @@ -11,14 +11,15 @@
use clap::Parser;
use pacquet_diagnostics::{
enable_tracing_by_env,
miette::{IntoDiagnostic, Result, WrapErr},
miette::{set_panic_hook, IntoDiagnostic, Result, WrapErr},
};
use pacquet_executor::execute_shell;
use pacquet_npmrc::current_npmrc;
use pacquet_package_json::PackageJson;

pub async fn run_cli() -> Result<()> {
enable_tracing_by_env();
set_panic_hook();

Check warning on line 22 in crates/cli/src/lib.rs

View check run for this annotation

Codecov / codecov/patch

crates/cli/src/lib.rs#L22

Added line #L22 was not covered by tests
let cli = Cli::parse();
run_commands(cli).await
}
Expand Down