Skip to content

Commit 9b57881

Browse files
committedJan 9, 2025
Fetch concurrently for non-first-match index strategies
1 parent 15ec830 commit 9b57881

File tree

1 file changed

+77
-29
lines changed

1 file changed

+77
-29
lines changed
 

‎crates/uv-client/src/registry_client.rs

Lines changed: 77 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use async_http_range_reader::AsyncHttpRangeReader;
2-
use futures::{FutureExt, TryStreamExt};
2+
use futures::{FutureExt, StreamExt, TryStreamExt};
33
use http::HeaderMap;
44
use itertools::Either;
55
use reqwest::{Client, Response, StatusCode};
@@ -247,38 +247,86 @@ impl RegistryClient {
247247
}
248248

249249
let mut results = Vec::new();
250-
for index in it {
251-
match self.simple_single_index(package_name, index).await {
252-
Ok(metadata) => {
253-
results.push((index, metadata));
254-
255-
// If we're only using the first match, we can stop here.
256-
if self.index_strategy == IndexStrategy::FirstIndex {
257-
break;
258-
}
259-
}
260-
Err(err) => match err.into_kind() {
261-
// The package could not be found in the remote index.
262-
ErrorKind::WrappedReqwestError(url, err) => match err.status() {
263-
Some(StatusCode::NOT_FOUND) => {}
264-
Some(StatusCode::UNAUTHORIZED) => {
265-
capabilities.set_unauthorized(index.clone());
266-
}
267-
Some(StatusCode::FORBIDDEN) => {
268-
capabilities.set_forbidden(index.clone());
250+
251+
match self.index_strategy {
252+
// If we're searching for the first index that contains the package, fetch serially.
253+
IndexStrategy::FirstIndex => {
254+
for index in it {
255+
match self.simple_single_index(package_name, index).await {
256+
Ok(metadata) => {
257+
results.push((index, metadata));
258+
break;
269259
}
270-
_ => return Err(ErrorKind::WrappedReqwestError(url, err).into()),
271-
},
260+
Err(err) => match err.into_kind() {
261+
// The package could not be found in the remote index.
262+
ErrorKind::WrappedReqwestError(url, err) => match err.status() {
263+
Some(StatusCode::NOT_FOUND) => {}
264+
Some(StatusCode::UNAUTHORIZED) => {
265+
capabilities.set_unauthorized(index.clone());
266+
}
267+
Some(StatusCode::FORBIDDEN) => {
268+
capabilities.set_forbidden(index.clone());
269+
}
270+
_ => return Err(ErrorKind::WrappedReqwestError(url, err).into()),
271+
},
272+
273+
// The package is unavailable due to a lack of connectivity.
274+
ErrorKind::Offline(_) => {}
275+
276+
// The package could not be found in the local index.
277+
ErrorKind::FileNotFound(_) => {}
278+
279+
err => return Err(err.into()),
280+
},
281+
};
282+
}
283+
}
272284

273-
// The package is unavailable due to a lack of connectivity.
274-
ErrorKind::Offline(_) => {}
285+
// Otherwise, fetch concurrently.
286+
IndexStrategy::UnsafeBestMatch | IndexStrategy::UnsafeFirstMatch => {
287+
let fetches = futures::stream::iter(it)
288+
.map(|index| async move {
289+
match self.simple_single_index(package_name, index).await {
290+
Ok(metadata) => Ok(Some((index, metadata))),
291+
Err(err) => match err.into_kind() {
292+
// The package could not be found in the remote index.
293+
ErrorKind::WrappedReqwestError(url, err) => match err.status() {
294+
Some(StatusCode::NOT_FOUND) => Ok(None),
295+
Some(StatusCode::UNAUTHORIZED) => {
296+
capabilities.set_unauthorized(index.clone());
297+
Ok(None)
298+
}
299+
Some(StatusCode::FORBIDDEN) => {
300+
capabilities.set_forbidden(index.clone());
301+
Ok(None)
302+
}
303+
_ => Err(ErrorKind::WrappedReqwestError(url, err).into()),
304+
},
305+
306+
// The package is unavailable due to a lack of connectivity.
307+
ErrorKind::Offline(_) => Ok(None),
308+
309+
// The package could not be found in the local index.
310+
ErrorKind::FileNotFound(_) => Ok(None),
311+
312+
err => Err(err.into()),
313+
},
314+
}
315+
})
316+
.buffered(8);
275317

276-
// The package could not be found in the local index.
277-
ErrorKind::FileNotFound(_) => {}
318+
futures::pin_mut!(fetches);
278319

279-
other => return Err(other.into()),
280-
},
281-
};
320+
while let Some(result) = fetches.next().await {
321+
match result {
322+
Ok(Some((index, metadata))) => {
323+
results.push((index, metadata));
324+
}
325+
Ok(None) => continue,
326+
Err(err) => return Err(err),
327+
}
328+
}
329+
}
282330
}
283331

284332
if results.is_empty() {

0 commit comments

Comments
 (0)