NixOS / nix

Nix, the purely functional package manager
https://nixos.org/
GNU Lesser General Public License v2.1
12.54k stars 1.5k forks source link

`fetchGit` with a fixed rev and no ref repeatedly hits the network #10773

Open marienz opened 5 months ago

marienz commented 5 months ago

Repeatedly fetching the same fixed rev using fetchGit hits the network each time once the cache is older than tarball-ttl (not just once to refresh the cache).

Steps To Reproduce

# Populate the cache:
nix eval --debug --expr 'builtins.fetchGit { url = "https://github.com/NixOS/nix.git"; rev = "2c42e7b8d9ea32e59c01334852599b548b214d31"; }'
# Wait 1 minute.
# Re-fetch the same rev (with tarball-ttl decreased to avoid having to wait an hour in the previous step). Observe this hits the network.
nix eval --option tarball-ttl 60  --debug --expr 'builtins.fetchGit { url = "https://github.com/NixOS/nix.git"; rev = "2c42e7b8d9ea32e59c01334852599b548b214d31"; }'
# Re-fetch the same rev again (within tarball-ttl from the second attempt). Observe this hits the network again.
nix eval --option tarball-ttl 60  --debug --expr 'builtins.fetchGit { url = "https://github.com/NixOS/nix.git"; rev = "2c42e7b8d9ea32e59c01334852599b548b214d31"; }'

This hits the network, seemingly to resolve the HEAD ref: the network hit occcurs between

resolved HEAD rev '2c42e7b8d9ea32e59c01334852599b548b214d31' for repo '/home/marienz/.cache/nix/gitv3/0rxngja0chlk8xlxh0qbhc9q5dznnlgkh32slphfhgyrb6rnbkqp'
resolved HEAD ref 'refs/heads/master' for repo 'https://github.com/NixOS/nix.git'

(I'm noticing this hits the network because it takes about 800ms instead of about 10ms, but I'm in Australia: if you're closer to Github the problem may be less noticeable.)

Expected behavior

If the requested rev is already cached, the cache is used without hitting the network. Or if it is necessary to verify the requested rev is obtainable from a particular ref (to avoid #7120): this verification only occurs once every tarball-ttl, not on every attempt once the cache is older than tarball-ttl.

nix-env --version output nix-env (Nix) 2.22.1

Additional context

Nix 2.18.2 does not have this problem.

It looks like the network hit occurs from the getDefaultRef() call in git.cc: passing in some ref makes me hit the cache again. (Any value for ref seems to work, although I'm guessing that's only because of #7120.) From there we end up in readHeadCached() which hits the network if the cached HEAD file is older than tarball-ttl, seemingly without updating that file.

6830 is somewhat related: that issue points out that caching revs is undesirable if Nix is fetching by ref (without a rev specified). If a rev is specified, caching seems very desirable.

Priorities

Add :+1: to issues you find important.

nixos-discourse commented 4 months ago

This issue has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/2024-05-29-nix-team-meeting-minutes-148/46195/1

mode89 commented 3 months ago

Same here. Can confirm that this behavior is observed on 2.23, but not on 2.18.