diff --git a/crates/symbolicator/src/services/download/mod.rs b/crates/symbolicator/src/services/download/mod.rs index 57bd6dd99..16bdd99e2 100644 --- a/crates/symbolicator/src/services/download/mod.rs +++ b/crates/symbolicator/src/services/download/mod.rs @@ -430,10 +430,10 @@ impl Iterator for SourceLocationIter<'_> { /// Computes a download timeout based on a content length in bytes and a per-gigabyte timeout. /// -/// The minimum timeout returned by this function is 1s. -fn content_length_timeout(content_length: u32, streaming_timeout: Duration) -> Duration { - let gb = content_length / (1024 * 1024 * 1024); - (streaming_timeout * gb).max(Duration::from_secs(1)) +/// Returns `content_length / 2^30 * timeout_per_gb`, with a minimum value of 10s. +fn content_length_timeout(content_length: u32, timeout_per_gb: Duration) -> Duration { + let gb = content_length as f64 / (1024.0 * 1024.0 * 1024.0); + timeout_per_gb.mul_f64(gb).max(Duration::from_secs(10)) } #[cfg(test)] @@ -506,4 +506,24 @@ mod tests { let item = &file_list[0]; assert_eq!(item.source_id(), source.id()); } + + #[test] + fn test_content_length_timeout() { + let timeout_per_gb = Duration::from_secs(30); + let one_gb = 1024 * 1024 * 1024; + + let timeout = |content_length| content_length_timeout(content_length, timeout_per_gb); + + // very short file + assert_eq!(timeout(100), Duration::from_secs(10)); + + // 0.5 GB + assert_eq!(timeout(one_gb / 2), timeout_per_gb / 2); + + // 1 GB + assert_eq!(timeout(one_gb), timeout_per_gb); + + // 1.5 GB + assert_eq!(timeout(one_gb * 3 / 2), timeout_per_gb.mul_f64(1.5)); + } }