From d553e8151249083d10828778f39f6e1821a0c609 Mon Sep 17 00:00:00 2001 From: Maximilian Marx Date: Sun, 27 Oct 2024 16:30:02 +0100 Subject: [PATCH] feat(http): respect Retry-After headers on HTTP 429 responses Fixes: #6 Signed-off-by: Maximilian Marx --- crates/nix-weather/src/net.rs | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/crates/nix-weather/src/net.rs b/crates/nix-weather/src/net.rs index b7616aa..b01e5dd 100644 --- a/crates/nix-weather/src/net.rs +++ b/crates/nix-weather/src/net.rs @@ -63,10 +63,31 @@ pub async fn nar_exists(client: Client, domain: &str, hash: &str, slide: u64) -> match response { Ok(response) if response.status().as_u16() == 200 => 1, Ok(response) if response.status().as_u16() == 404 => 0, - _ => { + Ok(response) if response.status().as_u16() == 429 => { // We're so fast now we get rate limited. - // - // Writng an actual sliding window seems kinda hard, + + let wait = if let Some(retry_after) = response.headers().get("Retry-After") { + if let Ok(seconds) = String::from_utf8_lossy(retry_after.as_bytes()).parse::() { + seconds * 1000 + } else { + slide + } + } else { + slide + }; + + sleep(Duration::from_millis(wait)).await; + Box::pin(nar_exists( + client, + domain, + hash, + std::cmp::min(slide * 2, MAX_SLIDE), + )) + .await + } + _ => { + // We might also be out of sockets, so let's wait on that + // Writing an actual sliding window seems kinda hard, // so we do this instead. log::trace!("rate limited! {slide}"); sleep(Duration::from_millis(slide)).await;