diff --git a/Cargo.lock b/Cargo.lock index 179108b1d521b..e2da3e3fdead4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6171,6 +6171,7 @@ dependencies = [ "serde-untagged", "serde_json", "thiserror 2.0.18", + "tokio", "tracing", "url", "uv-auth", diff --git a/crates/uv-bench/benches/uv.rs b/crates/uv-bench/benches/uv.rs index 0fbdf446a97eb..d8b1def9c2891 100644 --- a/crates/uv-bench/benches/uv.rs +++ b/crates/uv-bench/benches/uv.rs @@ -203,7 +203,7 @@ mod resolver { exclude_newer, sources, workspace_cache, - concurrency, + concurrency.clone(), Preview::default(), ); @@ -226,7 +226,11 @@ mod resolver { &hashes, &build_context, installed_packages, - DistributionDatabase::new(client, &build_context, concurrency.downloads), + DistributionDatabase::new( + client, + &build_context, + concurrency.downloads_semaphore.clone(), + ), )?; Ok(resolver.resolve().await?) diff --git a/crates/uv-build-frontend/src/lib.rs b/crates/uv-build-frontend/src/lib.rs index 87c7aea595156..1e18614e55d5b 100644 --- a/crates/uv-build-frontend/src/lib.rs +++ b/crates/uv-build-frontend/src/lib.rs @@ -223,11 +223,11 @@ pub struct SourceBuildContext { } impl SourceBuildContext { - /// Create a [`SourceBuildContext`] with the given concurrent build limit. - pub fn new(concurrent_builds: usize) -> Self { + /// Create a [`SourceBuildContext`] with the given shared concurrency semaphore. + pub fn new(concurrent_build_slots: Arc) -> Self { Self { default_resolution: Arc::default(), - concurrent_build_slots: Arc::new(Semaphore::new(concurrent_builds)), + concurrent_build_slots, } } } diff --git a/crates/uv-configuration/Cargo.toml b/crates/uv-configuration/Cargo.toml index 9a3678e3d4a2d..bc188ffbf1441 100644 --- a/crates/uv-configuration/Cargo.toml +++ b/crates/uv-configuration/Cargo.toml @@ -37,6 +37,7 @@ rustc-hash = { workspace = true } same-file = { workspace = true } schemars = { workspace = true, optional = true } serde = { workspace = true } +tokio = { workspace = true } serde-untagged = { workspace = true } thiserror = { workspace = true } tracing = { workspace = true } diff --git a/crates/uv-configuration/src/concurrency.rs b/crates/uv-configuration/src/concurrency.rs index 77860474e4268..ae468120d1392 100644 --- a/crates/uv-configuration/src/concurrency.rs +++ b/crates/uv-configuration/src/concurrency.rs @@ -1,7 +1,12 @@ +use std::fmt; use std::num::NonZeroUsize; +use std::sync::Arc; + +use tokio::sync::Semaphore; /// Concurrency limit settings. -#[derive(Copy, Clone, Debug)] +// TODO(konsti): We should find a pattern that doesn't require having both semaphores and counts. +#[derive(Clone)] pub struct Concurrency { /// The maximum number of concurrent downloads. /// @@ -15,15 +20,27 @@ pub struct Concurrency { /// /// Note this value must be non-zero. pub installs: usize, + /// A global semaphore to limit the number of concurrent downloads. + pub downloads_semaphore: Arc, + /// A global semaphore to limit the number of concurrent builds. + pub builds_semaphore: Arc, +} + +/// Custom `Debug` to hide semaphore fields from `--show-settings` output. +#[expect(clippy::missing_fields_in_debug)] +impl fmt::Debug for Concurrency { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Concurrency") + .field("downloads", &self.downloads) + .field("builds", &self.builds) + .field("installs", &self.installs) + .finish() + } } impl Default for Concurrency { fn default() -> Self { - Self { - downloads: Self::DEFAULT_DOWNLOADS, - builds: Self::threads(), - installs: Self::threads(), - } + Self::new(Self::DEFAULT_DOWNLOADS, Self::threads(), Self::threads()) } } @@ -31,6 +48,17 @@ impl Concurrency { // The default concurrent downloads limit. pub const DEFAULT_DOWNLOADS: usize = 50; + /// Create a new [`Concurrency`] with the given limits. + pub fn new(downloads: usize, builds: usize, installs: usize) -> Self { + Self { + downloads, + builds, + installs, + downloads_semaphore: Arc::new(Semaphore::new(downloads)), + builds_semaphore: Arc::new(Semaphore::new(builds)), + } + } + // The default concurrent builds and install limit. pub fn threads() -> usize { std::thread::available_parallelism() diff --git a/crates/uv-dispatch/src/lib.rs b/crates/uv-dispatch/src/lib.rs index 2f45bb4a3f0f3..7c66b7d38eec6 100644 --- a/crates/uv-dispatch/src/lib.rs +++ b/crates/uv-dispatch/src/lib.rs @@ -147,7 +147,7 @@ impl<'a> BuildDispatch<'a> { build_options, hasher, exclude_newer, - source_build_context: SourceBuildContext::new(concurrency.builds), + source_build_context: SourceBuildContext::new(concurrency.builds_semaphore.clone()), build_extra_env_vars: FxHashMap::default(), sources, workspace_cache, @@ -264,8 +264,12 @@ impl BuildContext for BuildDispatch<'_> { self.hasher, self, EmptyInstalledPackages, - DistributionDatabase::new(self.client, self, self.concurrency.downloads) - .with_build_stack(build_stack), + DistributionDatabase::new( + self.client, + self, + self.concurrency.downloads_semaphore.clone(), + ) + .with_build_stack(build_stack), )?; let resolution = Resolution::from(resolver.resolve().await.with_context(|| { format!( @@ -353,8 +357,12 @@ impl BuildContext for BuildDispatch<'_> { tags, self.hasher, self.build_options, - DistributionDatabase::new(self.client, self, self.concurrency.downloads) - .with_build_stack(build_stack), + DistributionDatabase::new( + self.client, + self, + self.concurrency.downloads_semaphore.clone(), + ) + .with_build_stack(build_stack), ); debug!( diff --git a/crates/uv-distribution/src/distribution_database.rs b/crates/uv-distribution/src/distribution_database.rs index a47cf3671c1fb..8f1dc9670c5fd 100644 --- a/crates/uv-distribution/src/distribution_database.rs +++ b/crates/uv-distribution/src/distribution_database.rs @@ -58,12 +58,12 @@ impl<'a, Context: BuildContext> DistributionDatabase<'a, Context> { pub fn new( client: &'a RegistryClient, build_context: &'a Context, - concurrent_downloads: usize, + downloads_semaphore: Arc, ) -> Self { Self { build_context, builder: SourceDistributionBuilder::new(build_context), - client: ManagedClient::new(client, concurrent_downloads), + client: ManagedClient::new(client, downloads_semaphore), reporter: None, } } @@ -1151,15 +1151,15 @@ impl<'a, Context: BuildContext> DistributionDatabase<'a, Context> { /// A wrapper around `RegistryClient` that manages a concurrency limit. pub struct ManagedClient<'a> { pub unmanaged: &'a RegistryClient, - control: Semaphore, + control: Arc, } impl<'a> ManagedClient<'a> { - /// Create a new `ManagedClient` using the given client and concurrency limit. - fn new(client: &'a RegistryClient, concurrency: usize) -> Self { + /// Create a new `ManagedClient` using the given client and concurrency semaphore. + fn new(client: &'a RegistryClient, control: Arc) -> Self { ManagedClient { unmanaged: client, - control: Semaphore::new(concurrency), + control, } } diff --git a/crates/uv/src/commands/build_frontend.rs b/crates/uv/src/commands/build_frontend.rs index 07a0eab3f318e..9d9b6e81e2ee9 100644 --- a/crates/uv/src/commands/build_frontend.rs +++ b/crates/uv/src/commands/build_frontend.rs @@ -146,7 +146,7 @@ pub(crate) async fn build_frontend( no_config, python_preference, python_downloads, - concurrency, + &concurrency, cache, printer, preview, @@ -193,7 +193,7 @@ async fn build_impl( no_config: bool, python_preference: PythonPreference, python_downloads: PythonDownloads, - concurrency: Concurrency, + concurrency: &Concurrency, cache: &Cache, printer: Printer, preview: Preview, @@ -469,7 +469,7 @@ async fn build_package( keyring_provider: KeyringProviderType, exclude_newer: ExcludeNewer, sources: NoSources, - concurrency: Concurrency, + concurrency: &Concurrency, build_options: &BuildOptions, sdist: bool, wheel: bool, @@ -630,7 +630,7 @@ async fn build_package( exclude_newer, sources.clone(), workspace_cache, - concurrency, + concurrency.clone(), preview, ); diff --git a/crates/uv/src/commands/pip/compile.rs b/crates/uv/src/commands/pip/compile.rs index fa9886b4ea334..068812db9a886 100644 --- a/crates/uv/src/commands/pip/compile.rs +++ b/crates/uv/src/commands/pip/compile.rs @@ -540,7 +540,7 @@ pub(crate) async fn pip_compile( exclude_newer.clone(), sources, WorkspaceCache::default(), - concurrency, + concurrency.clone(), preview, ); @@ -580,7 +580,7 @@ pub(crate) async fn pip_compile( &flat_index, &top_level_index, &build_dispatch, - concurrency, + &concurrency, options, Box::new(DefaultResolveLogger), printer, diff --git a/crates/uv/src/commands/pip/install.rs b/crates/uv/src/commands/pip/install.rs index a6a592ee550a3..7c7c822554bb9 100644 --- a/crates/uv/src/commands/pip/install.rs +++ b/crates/uv/src/commands/pip/install.rs @@ -486,7 +486,7 @@ pub(crate) async fn pip_install( exclude_newer.clone(), sources.clone(), WorkspaceCache::default(), - concurrency, + concurrency.clone(), preview, ); @@ -595,7 +595,7 @@ pub(crate) async fn pip_install( &flat_index, state.index(), &build_dispatch, - concurrency, + &concurrency, options, Box::new(DefaultResolveLogger), printer, @@ -640,7 +640,7 @@ pub(crate) async fn pip_install( exclude_newer.clone(), sources, WorkspaceCache::default(), - concurrency, + concurrency.clone(), preview, ); @@ -658,7 +658,7 @@ pub(crate) async fn pip_install( &tags, &client, state.in_flight(), - concurrency, + &concurrency, &build_dispatch, &cache, &environment, diff --git a/crates/uv/src/commands/pip/list.rs b/crates/uv/src/commands/pip/list.rs index 2dfe6db1f7c5d..cf99065e41f72 100644 --- a/crates/uv/src/commands/pip/list.rs +++ b/crates/uv/src/commands/pip/list.rs @@ -7,7 +7,6 @@ use itertools::Itertools; use owo_colors::OwoColorize; use rustc_hash::{FxHashMap, FxHashSet}; use serde::Serialize; -use tokio::sync::Semaphore; use tracing::debug; use unicode_width::UnicodeWidthStr; @@ -117,7 +116,7 @@ pub(crate) async fn pip_list( .markers(environment.interpreter().markers()) .platform(environment.interpreter().platform()) .build(); - let download_concurrency = Semaphore::new(concurrency.downloads); + let download_concurrency = concurrency.downloads_semaphore.clone(); // Determine the platform tags. let interpreter = environment.interpreter(); diff --git a/crates/uv/src/commands/pip/operations.rs b/crates/uv/src/commands/pip/operations.rs index 870daa6c0582a..cbe1da0901718 100644 --- a/crates/uv/src/commands/pip/operations.rs +++ b/crates/uv/src/commands/pip/operations.rs @@ -128,7 +128,7 @@ pub(crate) async fn resolve( flat_index: &FlatIndex, index: &InMemoryIndex, build_dispatch: &BuildDispatch<'_>, - concurrency: Concurrency, + concurrency: &Concurrency, options: Options, logger: Box, printer: Printer, @@ -156,7 +156,11 @@ pub(crate) async fn resolve( NamedRequirementsResolver::new( hasher, index, - DistributionDatabase::new(client, build_dispatch, concurrency.downloads), + DistributionDatabase::new( + client, + build_dispatch, + concurrency.downloads_semaphore.clone(), + ), ) .with_reporter(Arc::new(ResolverReporter::from(printer))) .resolve(unnamed.into_iter()) @@ -170,7 +174,11 @@ pub(crate) async fn resolve( extras, hasher, index, - DistributionDatabase::new(client, build_dispatch, concurrency.downloads), + DistributionDatabase::new( + client, + build_dispatch, + concurrency.downloads_semaphore.clone(), + ), ) .with_reporter(Arc::new(ResolverReporter::from(printer))) .resolve(source_trees.iter()) @@ -278,7 +286,11 @@ pub(crate) async fn resolve( NamedRequirementsResolver::new( hasher, index, - DistributionDatabase::new(client, build_dispatch, concurrency.downloads), + DistributionDatabase::new( + client, + build_dispatch, + concurrency.downloads_semaphore.clone(), + ), ) .with_reporter(Arc::new(ResolverReporter::from(printer))) .resolve(unnamed.into_iter()) @@ -309,7 +321,11 @@ pub(crate) async fn resolve( &overrides, hasher, index, - DistributionDatabase::new(client, build_dispatch, concurrency.downloads), + DistributionDatabase::new( + client, + build_dispatch, + concurrency.downloads_semaphore.clone(), + ), ) .with_reporter(Arc::new(ResolverReporter::from(printer))) .resolve(&resolver_env) @@ -357,7 +373,11 @@ pub(crate) async fn resolve( hasher, build_dispatch, installed_packages, - DistributionDatabase::new(client, build_dispatch, concurrency.downloads), + DistributionDatabase::new( + client, + build_dispatch, + concurrency.downloads_semaphore.clone(), + ), )? .with_reporter(Arc::new(reporter)); @@ -544,7 +564,7 @@ pub(crate) async fn install( tags: &Tags, client: &RegistryClient, in_flight: &InFlight, - concurrency: Concurrency, + concurrency: &Concurrency, build_dispatch: &BuildDispatch<'_>, cache: &Cache, venv: &PythonEnvironment, @@ -685,7 +705,7 @@ pub(crate) async fn install( } if compile { - compile_bytecode(venv, &concurrency, cache, printer).await?; + compile_bytecode(venv, concurrency, cache, printer).await?; } // Construct a summary of the changes made to the environment. @@ -722,7 +742,7 @@ async fn execute_plan( tags: &Tags, client: &RegistryClient, in_flight: &InFlight, - concurrency: Concurrency, + concurrency: &Concurrency, build_dispatch: &BuildDispatch<'_>, cache: &Cache, venv: &PythonEnvironment, @@ -749,7 +769,11 @@ async fn execute_plan( tags, hasher, build_options, - DistributionDatabase::new(client, build_dispatch, concurrency.downloads), + DistributionDatabase::new( + client, + build_dispatch, + concurrency.downloads_semaphore.clone(), + ), ) .with_reporter(Arc::new( PrepareReporter::from(printer).with_length(remote.len() as u64), diff --git a/crates/uv/src/commands/pip/sync.rs b/crates/uv/src/commands/pip/sync.rs index 6f5ddc962281c..2515cc086d9f6 100644 --- a/crates/uv/src/commands/pip/sync.rs +++ b/crates/uv/src/commands/pip/sync.rs @@ -393,7 +393,7 @@ pub(crate) async fn pip_sync( exclude_newer.clone(), sources.clone(), WorkspaceCache::default(), - concurrency, + concurrency.clone(), preview, ); @@ -486,7 +486,7 @@ pub(crate) async fn pip_sync( &flat_index, state.index(), &build_dispatch, - concurrency, + &concurrency, options, Box::new(DefaultResolveLogger), printer, @@ -531,7 +531,7 @@ pub(crate) async fn pip_sync( exclude_newer.clone(), sources, WorkspaceCache::default(), - concurrency, + concurrency.clone(), preview, ); @@ -549,7 +549,7 @@ pub(crate) async fn pip_sync( &tags, &client, state.in_flight(), - concurrency, + &concurrency, &build_dispatch, &cache, &environment, diff --git a/crates/uv/src/commands/pip/tree.rs b/crates/uv/src/commands/pip/tree.rs index e1721c749d342..9368cf3a43487 100644 --- a/crates/uv/src/commands/pip/tree.rs +++ b/crates/uv/src/commands/pip/tree.rs @@ -9,7 +9,6 @@ use petgraph::Direction; use petgraph::graph::{EdgeIndex, NodeIndex}; use petgraph::prelude::EdgeRef; use rustc_hash::{FxHashMap, FxHashSet}; -use tokio::sync::Semaphore; use uv_cache::{Cache, Refresh}; use uv_cache_info::Timestamp; @@ -100,7 +99,7 @@ pub(crate) async fn pip_tree( .markers(environment.interpreter().markers()) .platform(environment.interpreter().platform()) .build(); - let download_concurrency = Semaphore::new(concurrency.downloads); + let download_concurrency = concurrency.downloads_semaphore.clone(); // Determine the platform tags. let interpreter = environment.interpreter(); diff --git a/crates/uv/src/commands/project/add.rs b/crates/uv/src/commands/project/add.rs index 86d45c35a41b7..bf2481adeb5f8 100644 --- a/crates/uv/src/commands/project/add.rs +++ b/crates/uv/src/commands/project/add.rs @@ -459,7 +459,7 @@ pub(crate) async fn add( sources, // No workspace caching since `uv add` changes the workspace definition. WorkspaceCache::default(), - concurrency, + concurrency.clone(), preview, ); @@ -467,7 +467,11 @@ pub(crate) async fn add( NamedRequirementsResolver::new( &hasher, state.index(), - DistributionDatabase::new(&client, &build_dispatch, concurrency.downloads), + DistributionDatabase::new( + &client, + &build_dispatch, + concurrency.downloads_semaphore.clone(), + ), ) .with_reporter(Arc::new(ResolverReporter::from(printer))) .resolve(unnamed.into_iter()) @@ -750,7 +754,7 @@ pub(crate) async fn add( &settings, &client_builder, installer_metadata, - concurrency, + &concurrency, cache, printer, preview, @@ -992,7 +996,7 @@ async fn lock_and_sync( settings: &ResolverInstallerSettings, client_builder: &BaseClientBuilder<'_>, installer_metadata: bool, - concurrency: Concurrency, + concurrency: &Concurrency, cache: &Cache, printer: Printer, preview: Preview, diff --git a/crates/uv/src/commands/project/environment.rs b/crates/uv/src/commands/project/environment.rs index 8d9d21b7c77d3..144f650302f96 100644 --- a/crates/uv/src/commands/project/environment.rs +++ b/crates/uv/src/commands/project/environment.rs @@ -119,7 +119,7 @@ impl CachedEnvironment { resolve: Box, install: Box, installer_metadata: bool, - concurrency: Concurrency, + concurrency: &Concurrency, cache: &Cache, printer: Printer, preview: Preview, diff --git a/crates/uv/src/commands/project/export.rs b/crates/uv/src/commands/project/export.rs index 81f39a93ab366..fc1ebe800415a 100644 --- a/crates/uv/src/commands/project/export.rs +++ b/crates/uv/src/commands/project/export.rs @@ -208,7 +208,7 @@ pub(crate) async fn export( &client_builder, &state, Box::new(DefaultResolveLogger), - concurrency, + &concurrency, cache, &workspace_cache, printer, diff --git a/crates/uv/src/commands/project/lock.rs b/crates/uv/src/commands/project/lock.rs index a8bc45b574602..78ba8c1179c24 100644 --- a/crates/uv/src/commands/project/lock.rs +++ b/crates/uv/src/commands/project/lock.rs @@ -196,7 +196,7 @@ pub(crate) async fn lock( &client_builder, &state, Box::new(DefaultResolveLogger), - concurrency, + &concurrency, cache, &workspace_cache, printer, @@ -288,7 +288,7 @@ pub(super) struct LockOperation<'env> { client_builder: &'env BaseClientBuilder<'env>, state: &'env UniversalState, logger: Box, - concurrency: Concurrency, + concurrency: &'env Concurrency, cache: &'env Cache, workspace_cache: &'env WorkspaceCache, printer: Printer, @@ -303,7 +303,7 @@ impl<'env> LockOperation<'env> { client_builder: &'env BaseClientBuilder<'env>, state: &'env UniversalState, logger: Box, - concurrency: Concurrency, + concurrency: &'env Concurrency, cache: &'env Cache, workspace_cache: &'env WorkspaceCache, printer: Printer, @@ -459,7 +459,7 @@ async fn do_lock( client_builder: &BaseClientBuilder<'_>, state: &UniversalState, logger: Box, - concurrency: Concurrency, + concurrency: &Concurrency, cache: &Cache, workspace_cache: &WorkspaceCache, printer: Printer, @@ -783,11 +783,15 @@ async fn do_lock( exclude_newer.clone(), sources.clone(), workspace_cache.clone(), - concurrency, + concurrency.clone(), preview, ); - let database = DistributionDatabase::new(&client, &build_dispatch, concurrency.downloads); + let database = DistributionDatabase::new( + &client, + &build_dispatch, + concurrency.downloads_semaphore.clone(), + ); // If any of the resolution-determining settings changed, invalidate the lock. let existing_lock = if let Some(existing_lock) = existing_lock { diff --git a/crates/uv/src/commands/project/mod.rs b/crates/uv/src/commands/project/mod.rs index ee38063c10bc8..98f32fc31ce78 100644 --- a/crates/uv/src/commands/project/mod.rs +++ b/crates/uv/src/commands/project/mod.rs @@ -1793,7 +1793,7 @@ pub(crate) async fn resolve_names( settings: &ResolverInstallerSettings, client_builder: &BaseClientBuilder<'_>, state: &SharedState, - concurrency: Concurrency, + concurrency: &Concurrency, cache: &Cache, workspace_cache: &WorkspaceCache, printer: Printer, @@ -1919,7 +1919,7 @@ pub(crate) async fn resolve_names( exclude_newer.clone(), sources.clone(), workspace_cache.clone(), - concurrency, + concurrency.clone(), preview, ); @@ -1928,7 +1928,11 @@ pub(crate) async fn resolve_names( NamedRequirementsResolver::new( &hasher, state.index(), - DistributionDatabase::new(&client, &build_dispatch, concurrency.downloads), + DistributionDatabase::new( + &client, + &build_dispatch, + concurrency.downloads_semaphore.clone(), + ), ) .with_reporter(Arc::new(ResolverReporter::from(printer))) .resolve(unnamed.into_iter()) @@ -1987,7 +1991,7 @@ pub(crate) async fn resolve_environment( client_builder: &BaseClientBuilder<'_>, state: &PlatformState, logger: Box, - concurrency: Concurrency, + concurrency: &Concurrency, cache: &Cache, printer: Printer, preview: Preview, @@ -2155,7 +2159,7 @@ pub(crate) async fn resolve_environment( exclude_newer.clone(), sources.clone(), workspace_cache, - concurrency, + concurrency.clone(), preview, ); @@ -2203,7 +2207,7 @@ pub(crate) async fn sync_environment( state: &PlatformState, logger: Box, installer_metadata: bool, - concurrency: Concurrency, + concurrency: &Concurrency, cache: &Cache, printer: Printer, preview: Preview, @@ -2294,7 +2298,7 @@ pub(crate) async fn sync_environment( exclude_newer.clone(), sources, workspace_cache, - concurrency, + concurrency.clone(), preview, ); @@ -2360,7 +2364,7 @@ pub(crate) async fn update_environment( resolve: Box, install: Box, installer_metadata: bool, - concurrency: Concurrency, + concurrency: &Concurrency, cache: &Cache, workspace_cache: WorkspaceCache, dry_run: DryRun, @@ -2550,7 +2554,7 @@ pub(crate) async fn update_environment( exclude_newer.clone(), sources.clone(), workspace_cache, - concurrency, + concurrency.clone(), preview, ); diff --git a/crates/uv/src/commands/project/remove.rs b/crates/uv/src/commands/project/remove.rs index 958a61d73393b..f7ac54dc4511e 100644 --- a/crates/uv/src/commands/project/remove.rs +++ b/crates/uv/src/commands/project/remove.rs @@ -307,7 +307,7 @@ pub(crate) async fn remove( &client_builder, &state, Box::new(DefaultResolveLogger), - concurrency, + &concurrency, cache, &WorkspaceCache::default(), printer, @@ -365,7 +365,7 @@ pub(crate) async fn remove( &state, Box::new(DefaultInstallLogger), installer_metadata, - concurrency, + &concurrency, cache, WorkspaceCache::default(), DryRun::Disabled, diff --git a/crates/uv/src/commands/project/run.rs b/crates/uv/src/commands/project/run.rs index c3015632d052e..cf61fce52c567 100644 --- a/crates/uv/src/commands/project/run.rs +++ b/crates/uv/src/commands/project/run.rs @@ -282,7 +282,7 @@ hint: If you are running a script with `{}` in the shebang, you may need to incl } else { Box::new(SummaryResolveLogger) }, - concurrency, + &concurrency, &cache, &workspace_cache, printer, @@ -330,7 +330,7 @@ hint: If you are running a script with `{}` in the shebang, you may need to incl Box::new(SummaryInstallLogger) }, installer_metadata, - concurrency, + &concurrency, &cache, workspace_cache.clone(), DryRun::Disabled, @@ -447,7 +447,7 @@ hint: If you are running a script with `{}` in the shebang, you may need to incl Box::new(SummaryInstallLogger) }, installer_metadata, - concurrency, + &concurrency, &cache, workspace_cache.clone(), DryRun::Disabled, @@ -784,7 +784,7 @@ hint: If you are running a script with `{}` in the shebang, you may need to incl } else { Box::new(SummaryResolveLogger) }, - concurrency, + &concurrency, &cache, &workspace_cache, printer, @@ -873,7 +873,7 @@ hint: If you are running a script with `{}` in the shebang, you may need to incl Box::new(SummaryInstallLogger) }, installer_metadata, - concurrency, + &concurrency, &cache, workspace_cache.clone(), DryRun::Disabled, @@ -1028,7 +1028,7 @@ hint: If you are running a script with `{}` in the shebang, you may need to incl Box::new(SummaryInstallLogger) }, installer_metadata, - concurrency, + &concurrency, &cache, printer, preview, diff --git a/crates/uv/src/commands/project/sync.rs b/crates/uv/src/commands/project/sync.rs index 08cec6a4c4b1d..58af734033929 100644 --- a/crates/uv/src/commands/project/sync.rs +++ b/crates/uv/src/commands/project/sync.rs @@ -283,7 +283,7 @@ pub(crate) async fn sync( Box::new(DefaultResolveLogger), Box::new(DefaultInstallLogger), installer_metadata, - concurrency, + &concurrency, cache, workspace_cache.clone(), dry_run, @@ -350,7 +350,7 @@ pub(crate) async fn sync( &client_builder, &state, Box::new(DefaultResolveLogger), - concurrency, + &concurrency, cache, &workspace_cache, printer, @@ -410,7 +410,7 @@ pub(crate) async fn sync( &state, Box::new(DefaultInstallLogger), installer_metadata, - concurrency, + &concurrency, cache, workspace_cache, dry_run, @@ -613,7 +613,7 @@ pub(super) async fn do_sync( state: &PlatformState, logger: Box, installer_metadata: bool, - concurrency: Concurrency, + concurrency: &Concurrency, cache: &Cache, workspace_cache: WorkspaceCache, dry_run: DryRun, @@ -815,7 +815,7 @@ pub(super) async fn do_sync( exclude_newer.clone(), sources.clone(), workspace_cache.clone(), - concurrency, + concurrency.clone(), preview, ); diff --git a/crates/uv/src/commands/project/tree.rs b/crates/uv/src/commands/project/tree.rs index cfe27128180c2..3216ae60215ce 100644 --- a/crates/uv/src/commands/project/tree.rs +++ b/crates/uv/src/commands/project/tree.rs @@ -3,7 +3,6 @@ use std::path::Path; use anstream::print; use anyhow::{Error, Result}; use futures::StreamExt; -use tokio::sync::Semaphore; use uv_cache::{Cache, Refresh}; use uv_cache_info::Timestamp; use uv_client::{BaseClientBuilder, RegistryClientBuilder}; @@ -147,7 +146,7 @@ pub(crate) async fn tree( client_builder, &state, Box::new(DefaultResolveLogger), - concurrency, + &concurrency, cache, &WorkspaceCache::default(), printer, @@ -226,7 +225,7 @@ pub(crate) async fn tree( .index_locations(index_locations.clone()) .keyring(*keyring_provider) .build(); - let download_concurrency = Semaphore::new(concurrency.downloads); + let download_concurrency = concurrency.downloads_semaphore.clone(); // Initialize the client to fetch the latest version of each package. let client = LatestClient { diff --git a/crates/uv/src/commands/project/version.rs b/crates/uv/src/commands/project/version.rs index 0d359b7232775..d0cc18cf351f9 100644 --- a/crates/uv/src/commands/project/version.rs +++ b/crates/uv/src/commands/project/version.rs @@ -107,7 +107,7 @@ pub(crate) async fn project_version( client_builder, python_preference, python_downloads, - concurrency, + &concurrency, no_config, cache, short, @@ -328,7 +328,7 @@ pub(crate) async fn project_version( python_preference, python_downloads, installer_metadata, - concurrency, + &concurrency, no_config, cache, printer, @@ -437,7 +437,7 @@ async fn print_frozen_version( client_builder: BaseClientBuilder<'_>, python_preference: PythonPreference, python_downloads: PythonDownloads, - concurrency: Concurrency, + concurrency: &Concurrency, no_config: bool, cache: &Cache, short: bool, @@ -535,7 +535,7 @@ async fn lock_and_sync( python_preference: PythonPreference, python_downloads: PythonDownloads, installer_metadata: bool, - concurrency: Concurrency, + concurrency: &Concurrency, no_config: bool, cache: &Cache, printer: Printer, diff --git a/crates/uv/src/commands/tool/install.rs b/crates/uv/src/commands/tool/install.rs index 7885d54375518..a9b0ba40f0bf6 100644 --- a/crates/uv/src/commands/tool/install.rs +++ b/crates/uv/src/commands/tool/install.rs @@ -3,7 +3,6 @@ use std::str::FromStr; use anyhow::{Result, bail}; use owo_colors::OwoColorize; -use tokio::sync::Semaphore; use tracing::{debug, trace}; use uv_cache::{Cache, Refresh}; @@ -174,7 +173,7 @@ pub(crate) async fn install( &settings, &client_builder, &state, - concurrency, + &concurrency, &cache, &workspace_cache, printer, @@ -275,7 +274,7 @@ pub(crate) async fn install( // Initialize the capabilities. let capabilities = IndexCapabilities::default(); - let download_concurrency = Semaphore::new(concurrency.downloads); + let download_concurrency = concurrency.downloads_semaphore.clone(); // Initialize the client to fetch the latest version. let latest_client = LatestClient { @@ -362,7 +361,7 @@ pub(crate) async fn install( &settings, &client_builder, &state, - concurrency, + &concurrency, &cache, &workspace_cache, printer, @@ -388,7 +387,7 @@ pub(crate) async fn install( &settings, &client_builder, &state, - concurrency, + &concurrency, &cache, &workspace_cache, printer, @@ -578,7 +577,7 @@ pub(crate) async fn install( Box::new(DefaultResolveLogger), Box::new(DefaultInstallLogger), installer_metadata, - concurrency, + &concurrency, &cache, workspace_cache, DryRun::Disabled, @@ -619,7 +618,7 @@ pub(crate) async fn install( &client_builder, &state, Box::new(DefaultResolveLogger), - concurrency, + &concurrency, &cache, printer, preview, @@ -674,7 +673,7 @@ pub(crate) async fn install( &client_builder, &state, Box::new(DefaultResolveLogger), - concurrency, + &concurrency, &cache, printer, preview, @@ -715,7 +714,7 @@ pub(crate) async fn install( &state, Box::new(DefaultInstallLogger), installer_metadata, - concurrency, + &concurrency, &cache, printer, preview, diff --git a/crates/uv/src/commands/tool/run.rs b/crates/uv/src/commands/tool/run.rs index 0cf66f0868bc5..8b3c001893b5a 100644 --- a/crates/uv/src/commands/tool/run.rs +++ b/crates/uv/src/commands/tool/run.rs @@ -10,7 +10,6 @@ use console::Term; use itertools::Itertools; use owo_colors::OwoColorize; use tokio::process::Command; -use tokio::sync::Semaphore; use tracing::{debug, warn}; use uv_cache::{Cache, Refresh}; @@ -304,7 +303,7 @@ pub(crate) async fn run( python_preference, python_downloads, installer_metadata, - concurrency, + &concurrency, &cache, printer, preview, @@ -736,7 +735,7 @@ async fn get_or_create_environment( python_preference: PythonPreference, python_downloads: PythonDownloads, installer_metadata: bool, - concurrency: Concurrency, + concurrency: &Concurrency, cache: &Cache, printer: Printer, preview: Preview, @@ -929,7 +928,7 @@ async fn get_or_create_environment( // Initialize the capabilities. let capabilities = IndexCapabilities::default(); - let download_concurrency = Semaphore::new(concurrency.downloads); + let download_concurrency = concurrency.downloads_semaphore.clone(); // Initialize the client to fetch the latest version. let latest_client = LatestClient { diff --git a/crates/uv/src/commands/tool/upgrade.rs b/crates/uv/src/commands/tool/upgrade.rs index 8e843cc414c7b..1137fc3eccb2b 100644 --- a/crates/uv/src/commands/tool/upgrade.rs +++ b/crates/uv/src/commands/tool/upgrade.rs @@ -133,7 +133,7 @@ pub(crate) async fn upgrade( cache, &filesystem, installer_metadata, - concurrency, + &concurrency, preview, )) .await; @@ -268,7 +268,7 @@ async fn upgrade_tool( cache: &Cache, filesystem: &ResolverInstallerOptions, installer_metadata: bool, - concurrency: Concurrency, + concurrency: &Concurrency, preview: Preview, ) -> Result { // Ensure the tool is installed. diff --git a/crates/uv/src/settings.rs b/crates/uv/src/settings.rs index 9b291267e97d5..d2e6e1ca2df80 100644 --- a/crates/uv/src/settings.rs +++ b/crates/uv/src/settings.rs @@ -123,26 +123,26 @@ impl GlobalSettings { ColorChoice::Auto }, network_settings, - concurrency: Concurrency { - downloads: environment + concurrency: Concurrency::new( + environment .concurrency .downloads .combine(workspace.and_then(|workspace| workspace.globals.concurrent_downloads)) .map(NonZeroUsize::get) .unwrap_or(Concurrency::DEFAULT_DOWNLOADS), - builds: environment + environment .concurrency .builds .combine(workspace.and_then(|workspace| workspace.globals.concurrent_builds)) .map(NonZeroUsize::get) .unwrap_or_else(Concurrency::threads), - installs: environment + environment .concurrency .installs .combine(workspace.and_then(|workspace| workspace.globals.concurrent_installs)) .map(NonZeroUsize::get) .unwrap_or_else(Concurrency::threads), - }, + ), show_settings: args.show_settings, preview: Preview::from_args( resolve_preview(args, workspace, environment),