Skip to content

fetchers: tarball cache used past ttl - #16390

Open
tomberek wants to merge 1 commit into
NixOS:masterfrom
tomberek:tomberek/fetchers/narhash-cache-simple
Open

fetchers: tarball cache used past ttl#16390
tomberek wants to merge 1 commit into
NixOS:masterfrom
tomberek:tomberek/fetchers/narhash-cache-simple

Conversation

@tomberek

Copy link
Copy Markdown
Contributor

This is to fix a reported issue that fetchTarball with hashes were being re-fetched when TTLs expired. This adds another path to check if treeHash + narHash is still cached and uses it even if TTL is expired (except with TTL == 0 indicating a --refresh was used).

Another approach could be to explicitly add a narHash -> treeHash row. This seemed simpler for now.

Code was Co-Authored-By: Claude Sonnet 5 noreply@anthropic.com

@tomberek
tomberek requested review from figsoda and xokdvium August 29, 2026 14:04
@tomberek
tomberek requested a review from edolstra as a code owner August 29, 2026 14:04
@github-actions github-actions Bot added with-tests Issues related to testing. PRs with tests have some priority fetching Networking with the outside (non-Nix) world, input locking labels Aug 29, 2026
@tomberek
tomberek force-pushed the tomberek/fetchers/narhash-cache-simple branch from 2fd1482 to 017ceb4 Compare August 29, 2026 14:13

@figsoda figsoda left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks, this does fix the exact issue i was running into

one small question, it seems like it still tries to substitute this path every eval, is that expected?

$ nix eval -f . --option tarball-ttl 1 -vvvv
evaluating file '«nix-internal»/derivation-internal.nix'
evaluating file '/home/figsoda/cfg/default.nix'
performing daemon worker op: 10
substitution of '/nix/store/96zbdkrn93l6qjwq23xpxifqm8qcld3k-source': created
substitution of '/nix/store/96zbdkrn93l6qjwq23xpxifqm8qcld3k-source': woken up
querying info about missing paths...
starting pool of 24 threads
checking substituter 'https://cache.nixos.org' for path '/nix/store/96zbdkrn93l6qjwq23xpxifqm8qcld3k-source'
checking substituter 'https://fenix.cachix.org' for path '/nix/store/96zbdkrn93l6qjwq23xpxifqm8qcld3k-source'
checking substituter 'https://nix-community.cachix.org' for path '/nix/store/96zbdkrn93l6qjwq23xpxifqm8qcld3k-source'
entered goal loop
substitution of '/nix/store/96zbdkrn93l6qjwq23xpxifqm8qcld3k-source': init
acquiring write lock on "/nix/var/nix/temproots/3256124"
substitution of '/nix/store/96zbdkrn93l6qjwq23xpxifqm8qcld3k-source': trying next substituter
substitution of '/nix/store/96zbdkrn93l6qjwq23xpxifqm8qcld3k-source': trying next substituter
substitution of '/nix/store/96zbdkrn93l6qjwq23xpxifqm8qcld3k-source': trying next substituter
substitution of '/nix/store/96zbdkrn93l6qjwq23xpxifqm8qcld3k-source': done
substitution of '/nix/store/96zbdkrn93l6qjwq23xpxifqm8qcld3k-source': in final_awaiter
substitution of '/nix/store/96zbdkrn93l6qjwq23xpxifqm8qcld3k-source': goal destroyed
substitution of '/nix/store/96zbdkrn93l6qjwq23xpxifqm8qcld3k-source' failed, will try to download: error: path '/nix/store/96zbdkrn93l6qjwq23xpxifqm8qcld3k-source' is required, b
ut there is no substituter that can build it
locking path "/home/figsoda/.cache/nix/fetcher-locks/ebf60d0afb4b1d979846e02870fa1b3c576268fe51fba73265dcb861723ddef4"
lock acquired on "/home/figsoda/.cache/nix/fetcher-locks/ebf60d0afb4b1d979846e02870fa1b3c576268fe51fba73265dcb861723ddef4.lock"
using cache entry 'tarball:{"url":"https://github.com/nix-community/nix-init/archive/refs/tags/v0.3.5.tar.gz"}' -> '{"etag":"W/\"992d572c7fb46e916fa1e4a3c59bca0543bdce81c36f82f5a
91fc2cbe97abeab\"","lastModified":1778805587,"treeHash":"2cd10ceeaadcf77822106c3ad03514dd0cd72f45"}'
using cache entry 'treeHashToNarHash:{"treeHash":"2cd10ceeaadcf77822106c3ad03514dd0cd72f45"}' -> '{"narHash":"sha256-D4p0wZpIkDdfB5yrZYwVe+nBBoYqA/Lxm0PF1PfBwEs="}'
using cache entry 'treeHashToNarHash:{"treeHash":"2cd10ceeaadcf77822106c3ad03514dd0cd72f45"}' -> '{"narHash":"sha256-D4p0wZpIkDdfB5yrZYwVe+nBBoYqA/Lxm0PF1PfBwEs="}'
lock released on "/home/figsoda/.cache/nix/fetcher-locks/ebf60d0afb4b1d979846e02870fa1b3c576268fe51fba73265dcb861723ddef4.lock"
got tree '«https://github.com/nix-community/nix-init/archive/refs/tags/v0.3.5.tar.gz?narHash=sha256-D4p0wZpIkDdfB5yrZYwVe%2BnBBoYqA/Lxm0PF1PfBwEs%3D»/' from 'https://github.com/n
ix-community/nix-init/archive/refs/tags/v0.3.5.tar.gz?narHash=sha256-D4p0wZpIkDdfB5yrZYwVe%2BnBBoYqA/Lxm0PF1PfBwEs%3D'
using cache entry 'sourcePathToHash:{"fingerprint":"tarball:sha256-D4p0wZpIkDdfB5yrZYwVe+nBBoYqA/Lxm0PF1PfBwEs=","method":"nar","path":"/"}' -> '{"hash":"sha256-D4p0wZpIkDdfB5yrZ
YwVe+nBBoYqA/Lxm0PF1PfBwEs="}'
source path '«https://github.com/nix-community/nix-init/archive/refs/tags/v0.3.5.tar.gz?narHash=sha256-D4p0wZpIkDdfB5yrZYwVe%2BnBBoYqA/Lxm0PF1PfBwEs%3D»/' cache hit in '/nix/stor
e/96zbdkrn93l6qjwq23xpxifqm8qcld3k-source' (hash 'sha256-D4p0wZpIkDdfB5yrZYwVe+nBBoYqA/Lxm0PF1PfBwEs=')
performing daemon worker op: 1
evaluating file '/nix/store/96zbdkrn93l6qjwq23xpxifqm8qcld3k-source/default.nix'
«lambda @ /nix/store/96zbdkrn93l6qjwq23xpxifqm8qcld3k-source/default.nix:1:1»

compared to materialized

$ nix eval -f . --option tarball-ttl 1 -vvvv
evaluating file '«nix-internal»/derivation-internal.nix'
evaluating file '/home/figsoda/cfg/default.nix'
performing daemon worker op: 10
using substituted/cached path '/nix/store/96zbdkrn93l6qjwq23xpxifqm8qcld3k-source' for 'https://github.com/nix-community/nix-init/archive/refs/tags/v0.3.5.tar.gz'
performing daemon worker op: 1
performing daemon worker op: 1
evaluating file '/nix/store/96zbdkrn93l6qjwq23xpxifqm8qcld3k-source/default.nix'
«lambda @ /nix/store/96zbdkrn93l6qjwq23xpxifqm8qcld3k-source/default.nix:1:1»

@tomberek

Copy link
Copy Markdown
Contributor Author

Whats the difference in the setup of those two cases?

@figsoda

figsoda commented Aug 29, 2026

Copy link
Copy Markdown
Member

they both eval the same import (fetchTarball ...), in the first one the path is not materialized (only present in the tarball cache), in the second one the path already exists in the store

@xokdvium

Copy link
Copy Markdown
Contributor

Substitution is attempted unconditionally, though genitive narinfo cache would amortise this anyway. I guess the order could be swapped a bit to prioritise the tarball cache before substitution.

@tomberek

tomberek commented Aug 29, 2026

Copy link
Copy Markdown
Contributor Author

Substitution is attempted unconditionally, though genitive narinfo cache would amortise this anyway. I guess the order could be swapped a bit to prioritise the tarball cache before substitution.

This happens in fetchers.cc. So we'd need something like moving the substitution vs cache check vs actual fetching logic to be implemented on a per-fetcher basis. Or expose a cheap isAlreadyCached method?

(edit: something like this? 7287651)

@figsoda

figsoda commented Aug 29, 2026

Copy link
Copy Markdown
Member

btw i didnt mean to block this pr, this can totally be done in a separate pr, i was just curious about other improvements we can make

… expires

Nix re-checks a downloaded tarball's URL every hour by default (tarball-ttl),
even when the caller already pinned the exact content hash (narHash). That
pinned hash is enough to know the content is still correct without
contacting the server again, but nothing was checking for that case, so
fetches kept hitting the network on a schedule for no reason.

If the cached entry for a URL has gone stale but its content still matches
the pinned hash, reuse it instead of re-downloading. This is skipped when
the TTL is explicitly 0 (as with `--refresh`), since that means the caller
wants the source re-verified regardless of any hash we already have on file.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@tomberek
tomberek force-pushed the tomberek/fetchers/narhash-cache-simple branch from 017ceb4 to 984be4c Compare August 31, 2026 06:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fetching Networking with the outside (non-Nix) world, input locking with-tests Issues related to testing. PRs with tests have some priority

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants