Why
Two costs were left after #113:
- A push’s metadata delta was applied by the next reader, so the first page after a big push paid for the whole push.
- Search refreshed every visible repository before querying: one
symbolic-ref(opening the repo) and onerev-parse(checking the metadata ref) each, so an instance with N repositories paid 2N git processes per search. Measured in #100 at 510 req/s for a search over three repositories, p50 7 ms.
The check exists for a reason — a read must not trust an index a push could have moved — but it does not need a process, and the push itself can do the work.
Scope
- Post-receive refreshes the index after the refs have moved (and after a
followed request’s head has moved), using the
VOLE_INDEX_DBthe SSH server hands the hook. A failure is reported and ignored: the refs have landed, and the next read still repairs the rows. git.Repo.RefCommitresolves a branch ref by reading the loose ref file (what git writes for every branch update) and falls back torev-parsefor a packed ref, a symbolic ref, or a missing ref. Used by the index’sEnsureand the web’s metadata-head read.repo.Store.Metabuilds a repository handle without running git (no HEAD lookup). Search uses it, because it needs the directory and the ACL, not the default branch.
Acceptance
- A push that changes the
volebranch leaves the index rows current before the push command returns; a test queries the rows with noEnsurein between. - A search over N visible repositories starts no git process for the check;
symbolic-refandrev-parseare replaced by file reads. - A packed ref still resolves (the fallback), with a test that packs the refs.
search-findin the load harness improves on the #100 number (510 req/s, p50 7 ms at concurrency 4 over three repositories).
Notes
This does not remove the last git call on a metadata write (the ref update) or the diff/merge work a change page does; those are the work itself, not a check. A page whose index is stale because a hook did not run applies the delta on read, exactly as before.