diff --git a/nix-actions-cache/src/binary_cache.rs b/nix-actions-cache/src/binary_cache.rs index 1e94a35..60cb958 100644 --- a/nix-actions-cache/src/binary_cache.rs +++ b/nix-actions-cache/src/binary_cache.rs @@ -50,15 +50,23 @@ async fn get_narinfo( let store_path_hash = components[0].to_string(); let key = format!("{}.narinfo", store_path_hash); + if state + .narinfo_nagative_cache + .read() + .await + .contains(&store_path_hash) + { + return pull_through(&state, &path); + } + if let Some(url) = state.api.get_file_url(&[&key]).await? { return Ok(Redirect::temporary(&url)); } - if let Some(upstream) = &state.upstream { - Ok(Redirect::temporary(&format!("{}/{}", upstream, path))) - } else { - Err(Error::NotFound) - } + let mut negative_cache = state.narinfo_nagative_cache.write().await; + negative_cache.insert(store_path_hash); + + pull_through(&state, &path) } async fn put_narinfo( Extension(state): Extension, @@ -83,6 +91,12 @@ async fn put_narinfo( ); state.api.upload_file(allocation, stream).await?; + state + .narinfo_nagative_cache + .write() + .await + .remove(&store_path_hash); + Ok(()) } @@ -110,3 +124,11 @@ async fn put_nar( Ok(()) } + +fn pull_through(state: &State, path: &str) -> Result { + if let Some(upstream) = &state.upstream { + Ok(Redirect::temporary(&format!("{}/{}", upstream, path))) + } else { + Err(Error::NotFound) + } +} diff --git a/nix-actions-cache/src/main.rs b/nix-actions-cache/src/main.rs index 0d69b66..1e1346c 100644 --- a/nix-actions-cache/src/main.rs +++ b/nix-actions-cache/src/main.rs @@ -30,7 +30,7 @@ use clap::Parser; use daemonize::Daemonize; use tokio::{ runtime::Runtime, - sync::{oneshot, Mutex}, + sync::{oneshot, Mutex, RwLock}, }; use tracing_subscriber::filter::EnvFilter; @@ -89,6 +89,9 @@ struct StateInner { /// List of store paths originally present. original_paths: Mutex>, + + /// Set of store path hashes that are not present in GHAC. + narinfo_nagative_cache: RwLock>, } fn main() { @@ -120,6 +123,7 @@ fn main() { upstream: args.upstream.clone(), shutdown_sender: Mutex::new(Some(shutdown_sender)), original_paths: Mutex::new(HashSet::new()), + narinfo_nagative_cache: RwLock::new(HashSet::new()), }); let app = Router::new()