Skip to content

Commit 9dc71dd

Browse files
committed
fix: ci
1 parent afd2d1c commit 9dc71dd

1 file changed

Lines changed: 20 additions & 16 deletions

File tree

crates/pm/src/util/downloader.rs

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,18 @@ use super::retry::{RetryableError, build_dns_cached_client, create_retry_strateg
2020
static DOWNLOADER_CLIENT: Lazy<Client> = Lazy::new(build_dns_cached_client);
2121

2222
// OnceMap to ensure each (url, dest) pair is only downloaded once
23-
static DOWNLOAD_ONCE: Lazy<OnceMap<String, ()>> = Lazy::new(OnceMap::new);
23+
static DOWNLOAD_ONCE: Lazy<OnceMap<(String, PathBuf), ()>> = Lazy::new(OnceMap::new);
2424

2525
// ============ Buffer Pool ============
2626
// Reuse decompression buffers to reduce allocation overhead
2727
// Similar to Bun's ObjectPool pattern
2828

2929
const BUFFER_POOL_MAX_SIZE: usize = 8;
3030
const BUFFER_POOL_MIN_CAPACITY: usize = 2 * 1024 * 1024; // 2MB minimum
31+
const BUFFER_POOL_MAX_CAPACITY: usize = 64 * 1024 * 1024; // 64MB maximum
32+
const MIN_ESTIMATED_SIZE: usize = 16;
33+
const MAX_ESTIMATED_SIZE: usize = 512 * 1024 * 1024; // 512MB
34+
const DECOMPRESSION_RETRY_FACTOR: usize = 4;
3135

3236
/// Global buffer pool for decompression
3337
static BUFFER_POOL: Lazy<Mutex<Vec<Vec<u8>>>> =
@@ -60,7 +64,7 @@ fn acquire_buffer(required_capacity: usize) -> Vec<u8> {
6064
/// Return a buffer to the pool for reuse
6165
fn release_buffer(mut buf: Vec<u8>) {
6266
// Only keep buffers that are reasonably sized
63-
if buf.capacity() < BUFFER_POOL_MIN_CAPACITY || buf.capacity() > 64 * 1024 * 1024 {
67+
if buf.capacity() < BUFFER_POOL_MIN_CAPACITY || buf.capacity() > BUFFER_POOL_MAX_CAPACITY {
6468
tracing::trace!(
6569
"buffer pool: dropped (capacity={}, too small or too large)",
6670
buf.capacity()
@@ -123,10 +127,10 @@ fn sanitize_path_for_windows(base: &Path, relative: &Path) -> PathBuf {
123127

124128
/// Download and extract a tarball to the destination directory.
125129
///
126-
/// Uses OnceMap to ensure each URL is only downloaded once,
130+
/// Uses OnceMap to ensure each (url, dest) pair is only downloaded once,
127131
/// even when called concurrently from multiple tasks.
128132
pub async fn download(url: &str, dest: &Path) -> Result<()> {
129-
let key = url.to_string();
133+
let key = (url.to_string(), dest.to_path_buf());
130134

131135
DOWNLOAD_ONCE
132136
.get_or_init(key, || async {
@@ -219,7 +223,7 @@ fn estimate_uncompressed_size(gzip_data: &[u8]) -> usize {
219223
let last_4 = &gzip_data[gzip_data.len() - 4..];
220224
let size = u32::from_le_bytes([last_4[0], last_4[1], last_4[2], last_4[3]]) as usize;
221225
// Sanity check: if size is 0 or too small, use a reasonable estimate
222-
if !(16..=512 * 1024 * 1024).contains(&size) {
226+
if !(MIN_ESTIMATED_SIZE..=MAX_ESTIMATED_SIZE).contains(&size) {
223227
gzip_data.len() * 10
224228
} else {
225229
size
@@ -264,9 +268,8 @@ async fn extract_tarball(gzip_bytes: Bytes, dest: &Path) -> Result<()> {
264268
gzip_len,
265269
estimated_size
266270
);
267-
let new_size = estimated_size * 4;
268-
output.reserve(new_size - output.len());
269-
unsafe { output.set_len(new_size) };
271+
let new_size = estimated_size * DECOMPRESSION_RETRY_FACTOR;
272+
output.resize(new_size, 0);
270273
decompressor
271274
.gzip_decompress(&gzip_bytes, &mut output)
272275
.with_context(|| "gzip decompression failed")?
@@ -330,11 +333,11 @@ async fn extract_tarball(gzip_bytes: Bytes, dest: &Path) -> Result<()> {
330333
// First, create all directories (sequential to avoid race conditions)
331334
let mut created_dirs = HashSet::new();
332335
for entry in entries.iter() {
333-
if let Some(parent) = entry.path.parent() {
334-
if !created_dirs.contains(parent) {
335-
fs::create_dir_all(parent).ok();
336-
created_dirs.insert(parent.to_path_buf());
337-
}
336+
if let Some(parent) = entry.path.parent()
337+
&& created_dirs.insert(parent.to_path_buf())
338+
{
339+
fs::create_dir_all(parent)
340+
.with_context(|| format!("Failed to create directory: {}", parent.display()))?;
338341
}
339342
}
340343

@@ -349,7 +352,9 @@ async fn extract_tarball(gzip_bytes: Bytes, dest: &Path) -> Result<()> {
349352
{
350353
use std::os::unix::fs::PermissionsExt;
351354
let perms = fs::Permissions::from_mode(entry.mode);
352-
fs::set_permissions(&entry.path, perms).ok();
355+
fs::set_permissions(&entry.path, perms).with_context(|| {
356+
format!("Failed to set permissions: {}", entry.path.display())
357+
})?;
353358
}
354359
Ok(())
355360
})
@@ -453,8 +458,7 @@ mod tests {
453458
let url = url.clone();
454459
let dest = dest.clone();
455460
handles.push(task::spawn(async move {
456-
let bytes = download_bytes(&url).await.unwrap();
457-
extract_and_write(bytes, &dest).await.unwrap();
461+
download(&url, &dest).await.unwrap();
458462
}));
459463
}
460464
for h in handles {

0 commit comments

Comments
 (0)