Keeping a Fast Index Alive
A built index gives microsoft/tgrep a fast snapshot, but a developer’s repository does not remain still while searches are running. This chapter follows tgrep’s live server through edits, deletions, publication, and startup, focusing on who owns each piece of state and when a query may trust it. The practical result is a model of HybridIndex: a durable reader for the stable past, a live overlay for the recent present, and explicit readiness gates for everything in between.
A daemon makes the index reusable state
tgrep serve is not just a faster way to invoke the same command. It creates a long-lived process that opens an index, binds a localhost TCP listener, writes a small discovery record, and accepts newline-delimited JSON-RPC requests. A later tgrep command can find that record and send a search to the existing process. The server also takes an exclusive lock for its index directory, so two processes do not silently publish competing generations of the same index.
This arrangement moves work across a time boundary. A command that searches once has no reason to keep a reader alive after it exits. A server can pay the cost of opening and warming the index once, then share it across multiple clients. It can also keep data structures that are useful only when requests arrive repeatedly, such as decoded file content and a live view of recent changes.
The server’s core state has two layers. The first is the memory-mapped IndexReader from the previous chapter. It represents the last published disk generation. The second is LiveIndex, an in-memory overlay that records files changed after that generation. HybridIndex combines them when it serves a query. This is a deliberate division of authority: the reader owns the stable baseline, while the overlay owns exceptions to that baseline.
The overlay makes recent changes authoritative
Consider a file named src/parser.rs that was present when the disk index was built. If the file changes, its old postings are now dangerous: they can produce a candidate even when the new content no longer contains the searched fragment, and they cannot produce a candidate for a new fragment that the file now contains. Tgrep does not edit the old mmap in place. It inserts a new overlay entry for the path and treats that entry as authoritative.
An upsert removes the previous overlay entry for the path, extracts the new content’s trigrams and masks, assigns a new overlay file ID, and records the path. Overlay IDs carry a high-bit marker so code can distinguish them from IDs belonging to the disk reader. During lookup, HybridIndex combines reader postings with live postings but filters out a reader entry when the same path has an active overlay entry. The new content wins even though the old reader record remains physically present until a later publication.