diff --git a/doc/manual/rl-next/narinfo-cache-meta-ttl.md b/doc/manual/rl-next/narinfo-cache-meta-ttl.md new file mode 100644 index 000000000000..ba5116ace791 --- /dev/null +++ b/doc/manual/rl-next/narinfo-cache-meta-ttl.md @@ -0,0 +1,6 @@ +--- +synopsis: New setting `narinfo-cache-meta-ttl` +prs: [15287] +--- + +The new setting `narinfo-cache-meta-ttl` controls how long binary cache metadata (i.e. `/nix-cache-info`) is cached locally, in seconds. This was previously hard-coded to 7 days, which is still the default. As a result, you can now use `nix store info --refresh` to check whether a binary cache is still valid. diff --git a/src/libstore/include/nix/store/globals.hh b/src/libstore/include/nix/store/globals.hh index c827aea56770..3f2f122eb590 100644 --- a/src/libstore/include/nix/store/globals.hh +++ b/src/libstore/include/nix/store/globals.hh @@ -86,6 +86,17 @@ struct NarInfoDiskCacheSettings : public virtual Config would prevent trying to pull the path again and failing with a hash mismatch if the build isn't reproducible. )"}; + + Setting ttlMeta{ + this, + 7 * 24 * 3600, + "narinfo-cache-meta-ttl", + R"( + The TTL in seconds for caching binary cache metadata (i.e. + `/nix-cache-info`). This determines how long information about a + binary cache (such as its store directory, priority, and whether it + wants mass queries) is considered valid before being refreshed. + )"}; }; class Settings : public virtual Config, diff --git a/src/libstore/nar-info-disk-cache.cc b/src/libstore/nar-info-disk-cache.cc index 18932ca1250f..dfb679598eba 100644 --- a/src/libstore/nar-info-disk-cache.cc +++ b/src/libstore/nar-info-disk-cache.cc @@ -63,9 +63,6 @@ struct NarInfoDiskCacheImpl : NarInfoDiskCache /* How often to purge expired entries from the cache. */ const int purgeInterval = 24 * 3600; - /* How long to cache binary cache info (i.e. /nix-cache-info) */ - const int cacheInfoTtl = 7 * 24 * 3600; - struct Cache { int id; @@ -184,7 +181,7 @@ struct NarInfoDiskCacheImpl : NarInfoDiskCache { auto i = state.caches.find(uri); if (i == state.caches.end()) { - auto queryCache(state.queryCache.use()(uri)(time(0) - cacheInfoTtl)); + auto queryCache(state.queryCache.use()(uri)(time(0) - settings.ttlMeta)); if (!queryCache.next()) return std::nullopt; auto cache = Cache{ diff --git a/src/nix/main.cc b/src/nix/main.cc index dddb757afac3..992f37548e3e 100644 --- a/src/nix/main.cc +++ b/src/nix/main.cc @@ -564,12 +564,16 @@ void mainWrapped(int argc, char ** argv) fileTransferSettings.tries = 0; if (!fileTransferSettings.connectTimeout.overridden) fileTransferSettings.connectTimeout = 1; + auto & ttlMeta = settings.getNarInfoDiskCacheSettings().ttlMeta; + if (!ttlMeta.overridden) + ttlMeta = std::numeric_limits::max(); } if (args.refresh) { fetchSettings.tarballTtl = 0; settings.getNarInfoDiskCacheSettings().ttlNegative = 0; settings.getNarInfoDiskCacheSettings().ttlPositive = 0; + settings.getNarInfoDiskCacheSettings().ttlMeta = 0; } if (args.command->second->forceImpureByDefault() && !evalSettings.pureEval.overridden) { diff --git a/tests/functional/binary-cache.sh b/tests/functional/binary-cache.sh index 445845bba2a3..066fa026ed9b 100755 --- a/tests/functional/binary-cache.sh +++ b/tests/functional/binary-cache.sh @@ -312,3 +312,24 @@ nix-store --delete "$outPath" "$docPath" # -vvv is the level that logs during the loop timeout 60 nix-build --no-out-link -E "$expr" --option substituters "file://$cacheDir" \ --option trusted-binary-caches "file://$cacheDir" --no-require-sigs + + +# Test that the narinfo-cache-meta-ttl causes nix-cache-info to be cached, +# and that --refresh overrides it. + +# Populate the metadata cache by querying store info over HTTP. +_NIX_FORCE_HTTP=1 nix store info --store "file://$cacheDir" + +# Remove nix-cache-info from the binary cache. +rm "$cacheDir/nix-cache-info" + +# nix store info should still work because the metadata is cached +# (narinfo-cache-meta-ttl defaults to 7 days). +_NIX_FORCE_HTTP=1 nix store info --store "file://$cacheDir" + +# But with --refresh, it should fail because nix-cache-info is gone +# and the cached metadata TTL is overridden to 0. +_NIX_FORCE_HTTP=1 expectStderr 1 nix store info --store "file://$cacheDir" --refresh | grepQuiet "uploading.*is not supported" + +# Remove --refresh and it should work again. +_NIX_FORCE_HTTP=1 nix store info --store "file://$cacheDir"