Why
index.db only holds issues: issues, issue_labels, issue_assignees,
entity_numbers. Change requests, approvals, closes, comments and release
artifacts are read from the vole branch on every page that needs them, and the
repository header reads the whole requests subtree just to print a count.
#112 cut the page cost from 38–114 git calls to 5–19 on the fixture. What is left
is mostly the metadata read itself: rev-parse, ls-tree -r,
cat-file --batch-check, cat-file --batch on every page whose header shows
the open-changes badge. That read grows with the number of issues and comments,
so it is the part that gets worse with use.
Indexing the rest of the branch makes the header, the lists and search SQLite
reads, and it is the prerequisite for a search surface across issues, changes
and comments. The index stays derived: git remains authoritative, Rebuild and
the schema-version reset remain the recovery path.
Scope
Stage 1 — index the whole branch
- Tables:
requests,request_closes,request_approvals,comments(issues and requests),artifacts(release pointers). Schema version bumped so the existing drop-and-rebuild path applies. -
Ensurerefreshes issues and requests from the same path delta; a changed issue or request replaces its own rows, its comments, and its closes/approvals. Deletions remove the rows; numbers still come from history. -
Rebuild(vole admin index rebuild) and the first-read path index every table, not just issues. - Web: the repository header’s open-changes count, the change list and its state filters, the number lookup and the release artifact list read the index. Detail pages keep reading git, but a change page reads its one request instead of every request.
- The index is still disposable:
Rebuildreproduces every row from the branch alone.
Stage 2 — universal search
- FTS5 documents table over issue titles/bodies, request titles/bodies and
comment bodies, fed by the same refresh. Requires
sqlite_fts5in the build (verify workflow, packaging,CONTRIBUTING.md). - One search page across issues, changes and comments, plus the per-repo
surfaces that exist today.
[#42](/vole/n/42)numbers and ULID prefixes keep working. - Results are filtered by the same visibility rule the pages use: a private repository’s titles must not appear in a global search.
Stage 3 — drop the redundant reads
- Once stage 1 has run for a while, render detail pages from the index
(
Ensurealready runs before the read) and remove the remaining git reads from page rendering. - Re-measure with the harness from #99 before deciding whether the
persistent
cat-filepool is still worth it.
Acceptance
- A page that only shows the header count performs no metadata
cat-file/ls-tree(verified with a git shim, as in #112). vole admin index rebuildon a fixture with issues, changes, comments, approvals and artifacts reproduces identical rows.- The change list, its filters and its approval counts match what the git-read page showed, including stale approvals that name an older head.
- Search (stage 2) finds an issue title, a change title and a comment body from one query, and never returns a repository the viewer cannot read.
Costs
The DB grows with the branch (bodies are allowed up to 2 MiB per comment);
Rebuild becomes a full metadata parse per repository; every push re-indexes
the entities it touched.