Remove WaitMap dependency (#1183)

## Summary

This is an attempt to https://github.com/astral-sh/puffin/pull/1163 by
removing the `WaitMap` and gaining more granular control over the values
that we hold over `await` boundaries.
This commit is contained in:
Charlie Marsh
2024-01-30 12:25:22 -08:00
committed by GitHub
parent c129717b41
commit 3f5e7306a5
13 changed files with 130 additions and 218 deletions
Generated
+24 -93
View File
@@ -17,15 +17,6 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "ahash"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8fd72866655d1904d6b0997d0b07ba561047d070fbe29de039031c641b61217"
dependencies = [
"const-random",
]
[[package]]
name = "ahash"
version = "0.7.7"
@@ -251,7 +242,7 @@ checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837"
dependencies = [
"addr2line",
"cc",
"cfg-if 1.0.0",
"cfg-if",
"libc",
"miniz_oxide",
"object",
@@ -464,12 +455,6 @@ dependencies = [
"libc",
]
[[package]]
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "cfg-if"
version = "1.0.0"
@@ -602,26 +587,6 @@ dependencies = [
"windows-sys 0.52.0",
]
[[package]]
name = "const-random"
version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aaf16c9c2c612020bcfd042e170f6e32de9b9d75adb5277cdbbd2e2c8c8299a"
dependencies = [
"const-random-macro",
]
[[package]]
name = "const-random-macro"
version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e"
dependencies = [
"getrandom",
"once_cell",
"tiny-keccak",
]
[[package]]
name = "core-foundation"
version = "0.9.4"
@@ -653,7 +618,7 @@ version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
]
[[package]]
@@ -752,24 +717,13 @@ dependencies = [
"memchr",
]
[[package]]
name = "dashmap"
version = "3.11.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f260e2fc850179ef410018660006951c1b55b79e8087e87111a2c388994b9b5"
dependencies = [
"ahash 0.3.8",
"cfg-if 0.1.10",
"num_cpus",
]
[[package]]
name = "dashmap"
version = "5.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
"hashbrown 0.14.3",
"lock_api",
"once_cell",
@@ -910,7 +864,7 @@ version = "0.8.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
]
[[package]]
@@ -941,7 +895,7 @@ version = "0.2.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
"libc",
"redox_syscall 0.4.1",
"windows-sys 0.52.0",
@@ -1132,7 +1086,7 @@ version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
"js-sys",
"libc",
"wasi",
@@ -1247,7 +1201,7 @@ version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc52e53916c08643f1b56ec082790d1e86a32e58dc5268f897f313fbae7b4872"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
"crunchy",
]
@@ -1257,7 +1211,7 @@ version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
dependencies = [
"ahash 0.7.7",
"ahash",
]
[[package]]
@@ -1573,7 +1527,7 @@ version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
"js-sys",
"wasm-bindgen",
"web-sys",
@@ -1974,9 +1928,9 @@ dependencies = [
name = "once-map"
version = "0.0.1"
dependencies = [
"rustc-hash",
"dashmap",
"thiserror",
"waitmap",
"tokio",
]
[[package]]
@@ -2076,7 +2030,7 @@ version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
"instant",
"libc",
"redox_syscall 0.2.16",
@@ -2090,7 +2044,7 @@ version = "0.9.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
"libc",
"redox_syscall 0.4.1",
"smallvec",
@@ -2414,7 +2368,6 @@ dependencies = [
"tracing-subscriber",
"tracing-tree",
"url",
"waitmap",
"which",
]
@@ -2581,7 +2534,6 @@ dependencies = [
"tempfile",
"tokio",
"tracing",
"waitmap",
]
[[package]]
@@ -2708,7 +2660,6 @@ dependencies = [
"tokio",
"tracing",
"url",
"waitmap",
]
[[package]]
@@ -2757,7 +2708,7 @@ dependencies = [
"cache-key",
"chrono",
"clap",
"dashmap 5.5.3",
"dashmap",
"derivative",
"distribution-filename",
"distribution-types",
@@ -2797,7 +2748,6 @@ dependencies = [
"tokio-util",
"tracing",
"url",
"waitmap",
"zip",
]
@@ -2845,7 +2795,7 @@ version = "0.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a89dc7a5850d0e983be1ec2a463a171d20990487c3cfcd68b5363f1ee3d6fe0"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
"indoc",
"libc",
"memoffset",
@@ -3071,7 +3021,7 @@ version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "767be24c0da52e7448d495b8d162506a9aa125426651d547d545d6c2b4b65b62"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
"rustix",
"windows",
]
@@ -3490,7 +3440,7 @@ version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
"cpufeatures",
"digest",
]
@@ -3501,7 +3451,7 @@ version = "0.10.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
"cpufeatures",
"digest",
]
@@ -3706,7 +3656,7 @@ version = "3.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
"fastrand",
"redox_syscall 0.4.1",
"rustix",
@@ -3744,7 +3694,7 @@ version = "3.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adcb7fd841cd518e279be3d5a3eb0636409487998a4aff22f3de87b81e88384f"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
"proc-macro2",
"quote",
"syn 2.0.48",
@@ -3808,7 +3758,7 @@ version = "1.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
"once_cell",
]
@@ -3861,15 +3811,6 @@ dependencies = [
"time-core",
]
[[package]]
name = "tiny-keccak"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237"
dependencies = [
"crunchy",
]
[[package]]
name = "tinytemplate"
version = "1.2.1"
@@ -4288,16 +4229,6 @@ dependencies = [
"libc",
]
[[package]]
name = "waitmap"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28491611b6b9a0b9f027be139a4be792b13a20780100dd8b054d44dbf596d52b"
dependencies = [
"dashmap 3.11.10",
"smallvec",
]
[[package]]
name = "walkdir"
version = "2.4.0"
@@ -4329,7 +4260,7 @@ version = "0.2.90"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
"wasm-bindgen-macro",
]
@@ -4354,7 +4285,7 @@ version = "0.4.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bde2032aeb86bdfaecc8b261eef3cba735cc426c1f3a3416d1e0791be95fc461"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
"js-sys",
"wasm-bindgen",
"web-sys",
@@ -4643,7 +4574,7 @@ version = "0.50.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
"windows-sys 0.48.0",
]
-1
View File
@@ -104,7 +104,6 @@ unicode-width = { version = "0.1.11" }
unscanny = { version = "0.1.0" }
url = { version = "2.5.0" }
uuid = { version = "1.7.0", default-features = false }
waitmap = { version = "1.1.0" }
walkdir = { version = "2.4.0" }
which = { version = "6.0.0" }
zip = { version = "0.6.6", default-features = false, features = ["deflate"] }
+2 -2
View File
@@ -13,6 +13,6 @@ license = { workspace = true }
workspace = true
[dependencies]
rustc-hash = { workspace = true }
dashmap = { workspace = true }
thiserror = { workspace = true }
waitmap = { workspace = true }
tokio = { workspace = true }
+42 -50
View File
@@ -1,11 +1,9 @@
use std::borrow::Borrow;
use std::collections::hash_map::RandomState;
use std::hash::Hash;
use std::sync::Mutex;
use std::sync::Arc;
use rustc_hash::FxHashSet;
use waitmap::{Ref, WaitMap};
use dashmap::DashMap;
use tokio::sync::Notify;
/// Run tasks only once and store the results in a parallel hash map.
///
@@ -14,9 +12,7 @@ use waitmap::{Ref, WaitMap};
/// dist builds, we want to wait until the other task is done and get a reference to the same
/// result.
pub struct OnceMap<K: Eq + Hash, V> {
/// Computations that were started, including those that were finished.
started: Mutex<FxHashSet<K>>,
wait_map: WaitMap<K, V>,
items: DashMap<K, Value<V>>,
}
impl<K: Eq + Hash, V> OnceMap<K, V> {
@@ -25,72 +21,68 @@ impl<K: Eq + Hash, V> OnceMap<K, V> {
/// If this method returns `true`, you need to start a job and call [`OnceMap::done`] eventually
/// or other tasks will hang. If it returns `false`, this job is already in progress and you
/// can [`OnceMap::wait`] for the result.
pub fn register<Q>(&self, key: &Q) -> bool
where
K: Borrow<Q>,
Q: ?Sized + Hash + Eq + ToOwned<Owned = K>,
{
let mut lock = self.started.lock().unwrap();
if lock.contains(key) {
return false;
pub fn register(&self, key: K) -> bool {
let entry = self.items.entry(key);
match entry {
dashmap::mapref::entry::Entry::Occupied(_) => false,
dashmap::mapref::entry::Entry::Vacant(entry) => {
entry.insert(Value::Waiting(Arc::new(Notify::new())));
true
}
}
lock.insert(key.to_owned())
}
/// Like [`OnceMap::register`], but takes ownership of the key.
pub fn register_owned(&self, key: K) -> bool {
let mut lock = self.started.lock().unwrap();
if lock.contains(&key) {
return false;
}
lock.insert(key)
}
/// Submit the result of a job you registered.
pub fn done(&self, key: K, value: V) {
self.wait_map.insert(key, value);
if let Some(Value::Waiting(notify)) = self.items.insert(key, Value::Filled(Arc::new(value)))
{
notify.notify_waiters();
}
}
/// Wait for the result of a job that is running.
///
/// Will hang if [`OnceMap::done`] isn't called for this key.
pub async fn wait<Q: ?Sized + Hash + Eq>(
&self,
key: &Q,
) -> Result<Ref<'_, K, V, RandomState>, Error>
where
K: Borrow<Q> + for<'a> From<&'a Q>,
{
self.wait_map.wait(key).await.ok_or(Error::Canceled)
pub async fn wait(&self, key: &K) -> Option<Arc<V>> {
let entry = self.items.get(key)?;
match entry.value() {
Value::Filled(value) => Some(value.clone()),
Value::Waiting(notify) => {
let notify = notify.clone();
drop(entry);
notify.notified().await;
let entry = self.items.get(key).expect("map is append-only");
match entry.value() {
Value::Filled(value) => Some(value.clone()),
Value::Waiting(_) => unreachable!("notify was called"),
}
}
}
}
/// Return the result of a previous job, if any.
pub fn get<Q: ?Sized + Hash + Eq>(&self, key: &Q) -> Option<Ref<'_, K, V, RandomState>>
pub fn get<Q: ?Sized + Hash + Eq>(&self, key: &Q) -> Option<Arc<V>>
where
K: Borrow<Q>,
{
self.wait_map.get(key)
}
/// Cancel all waiting tasks.
///
/// Warning: waiting on tasks that have been canceled will cause the map to hang.
pub fn cancel_all(&self) {
self.wait_map.cancel_all();
let entry = self.items.get(key)?;
match entry.value() {
Value::Filled(value) => Some(value.clone()),
Value::Waiting(_) => None,
}
}
}
impl<K: Eq + Hash + Clone, V> Default for OnceMap<K, V> {
fn default() -> Self {
Self {
started: Mutex::new(FxHashSet::default()),
wait_map: WaitMap::new(),
items: DashMap::new(),
}
}
}
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("The operation was canceled")]
Canceled,
enum Value<V> {
Waiting(Arc<Notify>),
Filled(Arc<V>),
}
-1
View File
@@ -35,4 +35,3 @@ itertools = { workspace = true }
tempfile = { workspace = true }
tokio = { workspace = true }
tracing = { workspace = true }
waitmap = { workspace = true }
-1
View File
@@ -42,4 +42,3 @@ thiserror = { workspace = true }
tokio = { workspace = true }
tracing = { workspace = true }
url = { workspace = true }
waitmap = { workspace = true }
+11 -12
View File
@@ -29,8 +29,6 @@ pub enum Error {
Editable(#[from] puffin_distribution::Error),
#[error("Unzip failed in another thread: {0}")]
Thread(String),
#[error(transparent)]
OnceMap(#[from] once_map::Error),
}
/// Download, build, and unzip a set of distributions.
@@ -159,7 +157,7 @@ impl<'a, Context: BuildContext + Send + Sync> Downloader<'a, Context> {
#[instrument(skip_all, fields(name = % dist, size = ? dist.size(), url = dist.file().map(| file | file.url.to_string()).unwrap_or_default()))]
pub async fn get_wheel(&self, dist: Dist, in_flight: &InFlight) -> Result<CachedDist, Error> {
let id = dist.distribution_id();
let wheel = if in_flight.downloads.register(&id) {
if in_flight.downloads.register(id.clone()) {
let download: LocalWheel = self
.database
.get_or_build_wheel(dist.clone())
@@ -170,24 +168,25 @@ impl<'a, Context: BuildContext + Send + Sync> Downloader<'a, Context> {
match result {
Ok(cached) => {
in_flight.downloads.done(id, Ok(cached.clone()));
cached
Ok(cached)
}
Err(err) => {
in_flight.downloads.done(id, Err(err.to_string()));
return Err(err);
Err(err)
}
}
} else {
in_flight
let result = in_flight
.downloads
.wait(&id)
.await?
.value()
.clone()
.map_err(Error::Thread)?
};
.await
.expect("missing value for registered task");
Ok(wheel)
match result.as_ref() {
Ok(cached) => Ok(cached.clone()),
Err(err) => Err(Error::Thread(err.to_string())),
}
}
}
/// Unzip a locally-available wheel into the cache.
-1
View File
@@ -57,7 +57,6 @@ tokio = { workspace = true, features = ["macros"] }
tokio-util = { workspace = true, features = ["compat"] }
tracing = { workspace = true }
url = { workspace = true }
waitmap = { workspace = true }
zip = { workspace = true }
[dev-dependencies]
+3 -4
View File
@@ -36,8 +36,8 @@ pub enum ResolveError {
#[error(transparent)]
Join(#[from] tokio::task::JoinError),
#[error(transparent)]
OnceMap(#[from] once_map::Error),
#[error("Attempted to wait on an unregistered task")]
Unregistered,
#[error("Package metadata name `{metadata}` does not match given name `{given}`")]
NameMismatch {
@@ -193,8 +193,7 @@ impl NoSolutionError {
// these packages, but it's non-deterministic, and omitting them ensures that
// we represent the state of the resolver at the time of failure.
if visited.contains(name) {
if let Some(entry) = package_versions.get(name) {
let version_map = entry.value();
if let Some(version_map) = package_versions.get(name) {
available_versions.insert(
package.clone(),
version_map
+4 -8
View File
@@ -68,8 +68,7 @@ impl ResolutionGraph {
.clone();
// Add its hashes to the index.
if let Some(entry) = packages.get(package_name) {
let version_map = entry.value();
if let Some(version_map) = packages.get(package_name) {
hashes.insert(package_name.clone(), {
let mut hashes = version_map.hashes(version);
hashes.sort_unstable();
@@ -94,8 +93,7 @@ impl ResolutionGraph {
};
// Add its hashes to the index.
if let Some(entry) = packages.get(package_name) {
let version_map = entry.value();
if let Some(version_map) = packages.get(package_name) {
hashes.insert(package_name.clone(), {
let mut hashes = version_map.hashes(version);
hashes.sort_unstable();
@@ -110,10 +108,9 @@ impl ResolutionGraph {
PubGrubPackage::Package(package_name, Some(extra), None) => {
// Validate that the `extra` exists.
let dist = PubGrubDistribution::from_registry(package_name, version);
let entry = distributions
let metadata = distributions
.get(&dist.package_id())
.expect("Every package should have metadata");
let metadata = entry.value();
if !metadata.provides_extras.contains(extra) {
let pinned_package = pins
@@ -130,10 +127,9 @@ impl ResolutionGraph {
PubGrubPackage::Package(package_name, Some(extra), Some(url)) => {
// Validate that the `extra` exists.
let dist = PubGrubDistribution::from_url(package_name, url);
let entry = distributions
let metadata = distributions
.get(&dist.package_id())
.expect("Every package should have metadata");
let metadata = entry.value();
if !metadata.provides_extras.contains(extra) {
let url = redirects.get(url).map_or_else(
@@ -23,13 +23,3 @@ pub struct InMemoryIndex {
/// `git+https://github.com/pallets/flask.git@c2f65dd1cfff0672b902fd5b30815f0b4137214c`.
pub(crate) redirects: DashMap<Url, Url>,
}
impl InMemoryIndex {
/// Cancel all waiting tasks.
///
/// Warning: waiting on tasks that have been canceled will cause the index to hang.
pub(crate) fn cancel_all(&self) {
self.packages.cancel_all();
self.distributions.cancel_all();
}
}
+44 -34
View File
@@ -139,7 +139,7 @@ impl<'a, Provider: ResolverProvider> Resolver<'a, Provider> {
// Mock editable responses.
let package_id = dist.package_id();
index.distributions.register(&package_id);
index.distributions.register(package_id.clone());
index.distributions.done(package_id, metadata.clone());
editables.insert(
dist.name().clone(),
@@ -217,10 +217,6 @@ impl<'a, Provider: ResolverProvider> Resolver<'a, Provider> {
}
resolution = resolve_fut => {
resolution.map_err(|err| {
// Ensure that any waiting tasks are cancelled prior to accessing any of the
// index entries.
self.index.cancel_all();
// Add version information to improve unsat error messages.
if let ResolveError::NoSolution(err) = err {
ResolveError::NoSolution(
@@ -386,7 +382,7 @@ impl<'a, Provider: ResolverProvider> Resolver<'a, Provider> {
/// Visit a [`PubGrubPackage`] prior to selection. This should be called on a [`PubGrubPackage`]
/// before it is selected, to allow metadata to be fetched in parallel.
fn visit_package(
async fn visit_package(
&self,
package: &PubGrubPackage,
priorities: &mut PubGrubPriorities,
@@ -397,17 +393,23 @@ impl<'a, Provider: ResolverProvider> Resolver<'a, Provider> {
PubGrubPackage::Python(_) => {}
PubGrubPackage::Package(package_name, _extra, None) => {
// Emit a request to fetch the metadata for this package.
if self.index.packages.register(package_name) {
if self.index.packages.register(package_name.clone()) {
priorities.add(package_name.clone());
request_sink.unbounded_send(Request::Package(package_name.clone()))?;
// Yield to allow subscribers to continue, as the channel is sync.
tokio::task::yield_now().await;
}
}
PubGrubPackage::Package(package_name, _extra, Some(url)) => {
// Emit a request to fetch the metadata for this distribution.
let dist = Dist::from_url(package_name.clone(), url.clone())?;
if self.index.distributions.register_owned(dist.package_id()) {
if self.index.distributions.register(dist.package_id()) {
priorities.add(dist.name().clone());
request_sink.unbounded_send(Request::Dist(dist))?;
// Yield to allow subscribers to continue, as the channel is sync.
tokio::task::yield_now().await;
}
}
}
@@ -492,8 +494,12 @@ impl<'a, Provider: ResolverProvider> Resolver<'a, Provider> {
} else {
// Otherwise, assume this is a source distribution.
let dist = PubGrubDistribution::from_url(package_name, url);
let entry = self.index.distributions.wait(&dist.package_id()).await?;
let metadata = entry.value();
let metadata = self
.index
.distributions
.wait(&dist.package_id())
.await
.ok_or(ResolveError::Unregistered)?;
let version = &metadata.version;
if range.contains(version) {
Ok(Some(version.clone()))
@@ -505,13 +511,13 @@ impl<'a, Provider: ResolverProvider> Resolver<'a, Provider> {
PubGrubPackage::Package(package_name, extra, None) => {
// Wait for the metadata to be available.
let entry = self
let version_map = self
.index
.packages
.wait(package_name)
.instrument(info_span!("package_wait", %package_name))
.await?;
let version_map = entry.value();
.await
.ok_or(ResolveError::Unregistered)?;
self.visited.insert(package_name.clone());
if let Some(extra) = extra {
@@ -523,7 +529,8 @@ impl<'a, Provider: ResolverProvider> Resolver<'a, Provider> {
}
// Find a compatible version.
let Some(candidate) = self.selector.select(package_name, range, version_map) else {
let Some(candidate) = self.selector.select(package_name, range, &version_map)
else {
// Short circuit: we couldn't find _any_ compatible versions for a package.
return Ok(None);
};
@@ -567,13 +574,12 @@ impl<'a, Provider: ResolverProvider> Resolver<'a, Provider> {
let version = candidate.version().clone();
// Emit a request to fetch the metadata for this version.
if self
.index
.distributions
.register_owned(candidate.package_id())
{
if self.index.distributions.register(candidate.package_id()) {
let dist = candidate.resolve().dist.clone();
request_sink.unbounded_send(Request::Dist(dist))?;
// Yield to allow subscribers to continue, as the channel is sync.
tokio::task::yield_now().await;
}
Ok(Some(version))
@@ -613,7 +619,8 @@ impl<'a, Provider: ResolverProvider> Resolver<'a, Provider> {
debug!("Adding direct dependency: {package}{version}");
// Emit a request to fetch the metadata for this package.
self.visit_package(package, priorities, request_sink)?;
self.visit_package(package, priorities, request_sink)
.await?;
}
// Add a dependency on each editable.
@@ -661,7 +668,7 @@ impl<'a, Provider: ResolverProvider> Resolver<'a, Provider> {
// If the package is known to be incompatible, return the Python version as an
// incompatibility, and skip fetching the metadata.
if let Some(entry) = self.incompatibilities.get(&package_id) {
let requires_python = entry.value();
let requires_python = entry;
let version = requires_python
.iter()
.map(PubGrubSpecifier::try_from)
@@ -678,13 +685,13 @@ impl<'a, Provider: ResolverProvider> Resolver<'a, Provider> {
return Ok(Dependencies::Available(constraints));
}
let entry = self
let metadata = self
.index
.distributions
.wait(&package_id)
.instrument(info_span!("distributions_wait", %package_id))
.await?;
let metadata = entry.value();
.await
.ok_or(ResolveError::Unregistered)?;
let mut constraints = PubGrubDependencies::from_requirements(
&metadata.requires_dist,
@@ -699,7 +706,8 @@ impl<'a, Provider: ResolverProvider> Resolver<'a, Provider> {
debug!("Adding transitive dependency: {package}{version}");
// Emit a request to fetch the metadata for this package.
self.visit_package(package, priorities, request_sink)?;
self.visit_package(package, priorities, request_sink)
.await?;
}
// If a package has an extra, insert a constraint on the base package.
@@ -761,6 +769,9 @@ impl<'a, Provider: ResolverProvider> Resolver<'a, Provider> {
}
None => {}
}
// Yield to allow subscribers to continue, as the channel is sync.
tokio::task::yield_now().await;
}
Ok::<(), ResolveError>(())
@@ -809,12 +820,16 @@ impl<'a, Provider: ResolverProvider> Resolver<'a, Provider> {
// Pre-fetch the package and distribution metadata.
Request::Prefetch(package_name, range) => {
// Wait for the package metadata to become available.
let entry = self.index.packages.wait(&package_name).await?;
let version_map = entry.value();
let version_map = self
.index
.packages
.wait(&package_name)
.await
.ok_or(ResolveError::Unregistered)?;
// Try to find a compatible version. If there aren't any compatible versions,
// short-circuit and return `None`.
let Some(candidate) = self.selector.select(&package_name, &range, version_map)
let Some(candidate) = self.selector.select(&package_name, &range, &version_map)
else {
return Ok(None);
};
@@ -827,13 +842,8 @@ impl<'a, Provider: ResolverProvider> Resolver<'a, Provider> {
}
// Emit a request to fetch the metadata for this version.
if self
.index
.distributions
.register_owned(candidate.package_id())
{
if self.index.distributions.register(candidate.package_id()) {
let dist = candidate.resolve().dist.clone();
drop(entry);
let (metadata, precise) = self
.provider
-1
View File
@@ -68,7 +68,6 @@ tracing-durations-export = { workspace = true, features = ["plot"], optional = t
tracing-subscriber = { workspace = true }
tracing-tree = { workspace = true }
url = { workspace = true }
waitmap = { workspace = true }
which = { workspace = true }
[target.'cfg(target_os = "windows")'.dependencies]