pub struct Store { /* private fields */ }Expand description
A handle to the rq database.
Implementations§
Source§impl Store
impl Store
Sourcepub fn open(path: &Path) -> Result<Store>
pub fn open(path: &Path) -> Result<Store>
Open (creating if needed) the database at path, enabling WAL and
applying the schema.
Sourcepub fn open_in_memory() -> Result<Store>
pub fn open_in_memory() -> Result<Store>
Open an in-memory database — used by tests.
Examples found in repository?
29fn main() {
30 let root = PathBuf::from(std::env::args().nth(1).unwrap_or_else(|| ".".into()));
31
32 let mut store = Store::open_in_memory().expect("open store");
33 let stats = index::index_path(&mut store, &root).expect("index");
34 println!(
35 "indexed {} symbols from {} file(s) under {}",
36 stats.symbols,
37 stats.files_indexed,
38 root.display()
39 );
40
41 // warm up
42 for q in QUERIES {
43 let _ = search::search(&store, q, None, None, &search::ActiveFiles::default(), 10);
44 }
45
46 let mut times_us: Vec<u128> = Vec::new();
47 for _ in 0..200 {
48 for q in QUERIES {
49 let start = Instant::now();
50 let _ = search::search(&store, q, None, None, &search::ActiveFiles::default(), 10)
51 .expect("search");
52 times_us.push(start.elapsed().as_micros());
53 }
54 }
55 times_us.sort_unstable();
56
57 let pct = |p: f64| times_us[((times_us.len() as f64 - 1.0) * p).round() as usize];
58 println!(
59 "search over {} runs: p50 {} µs p95 {} µs max {} µs",
60 times_us.len(),
61 pct(0.50),
62 pct(0.95),
63 times_us[times_us.len() - 1],
64 );
65 let budget_us = 50_000;
66 let over = times_us.iter().filter(|&&t| t > budget_us).count();
67 println!("{}/{} runs exceeded the 50 ms budget", over, times_us.len());
68}Sourcepub fn upsert_repository(
&self,
identity: &RepoIdentity,
default_branch: Option<&str>,
) -> Result<i64>
pub fn upsert_repository( &self, identity: &RepoIdentity, default_branch: Option<&str>, ) -> Result<i64>
Insert or update a repository, returning its id.
Sourcepub fn upsert_checkout(
&self,
repository_id: i64,
root_path: &str,
branch: Option<&str>,
) -> Result<()>
pub fn upsert_checkout( &self, repository_id: i64, root_path: &str, branch: Option<&str>, ) -> Result<()>
Record (or update) a local checkout of a repository.
Sourcepub fn file_unchanged(
&self,
repository_id: i64,
path: &str,
content_hash: &str,
) -> Result<bool>
pub fn file_unchanged( &self, repository_id: i64, path: &str, content_hash: &str, ) -> Result<bool>
True if path is already indexed at this exact content hash — the
incremental-skip check.
Sourcepub fn file_mtimes(
&self,
repository_id: i64,
) -> Result<HashMap<String, Option<i64>>>
pub fn file_mtimes( &self, repository_id: i64, ) -> Result<HashMap<String, Option<i64>>>
Indexed path → stored mtime for a repository. The budgeted warm pass uses
this to skip unchanged files with a cheap stat (no read or re-hash).
Sourcepub fn replace_file_symbols(
&mut self,
repository_id: i64,
path: &str,
language: &str,
mtime: Option<i64>,
content_hash: &str,
symbols: &[Symbol],
) -> Result<()>
pub fn replace_file_symbols( &mut self, repository_id: i64, path: &str, language: &str, mtime: Option<i64>, content_hash: &str, symbols: &[Symbol], ) -> Result<()>
Replace all symbols for one file — the single-file form of
Store::replace_files (same upsert, hash-skip, and batching).
Sourcepub fn replace_files(
&mut self,
repository_id: i64,
files: &[FileSymbols],
) -> Result<(usize, usize)>
pub fn replace_files( &mut self, repository_id: i64, files: &[FileSymbols], ) -> Result<(usize, usize)>
Write many parsed files, one transaction per chunk — a batched fsync
instead of one per file, while bounding how much a single transaction
holds (a cold index of a huge repo would otherwise be one enormous txn).
A file whose content hash already matches the index is skipped (not
rewritten). Returns (files_written, symbols_written); skips don’t count.
Sourcepub fn defer_fts_insert(&self) -> Result<()>
pub fn defer_fts_insert(&self) -> Result<()>
Suspend per-row FTS maintenance for a cold bulk index: drop the
AFTER INSERT trigger so symbol inserts skip the expensive per-row
trigram tokenization. Pair with rebuild_fts, which
rebuilds the index in one pass and restores the trigger. No-op safe to
call when the trigger is already gone.
Sourcepub fn rebuild_fts(&self) -> Result<()>
pub fn rebuild_fts(&self) -> Result<()>
Rebuild the trigram FTS index from the symbols table in one bulk pass —
far cheaper than the per-row trigger on a cold index — then recreate the
AFTER INSERT trigger so later incremental writes stay in sync. The
inverse of defer_fts_insert. One transaction:
a concurrent writer either lands before the rebuild (and is captured by
it — the rebuild scans the whole symbols table) or after the trigger is
back, never in between.
Sourcepub fn fts_trigger_missing(&self) -> Result<bool>
pub fn fts_trigger_missing(&self) -> Result<bool>
Whether the AFTER INSERT FTS-sync trigger is currently absent — true
only mid-bulk-index (see defer_fts_insert)
or after one crashed before its rebuild_fts.
Sourcepub fn set_coverage(
&self,
repository_id: i64,
files_seen: i64,
files_indexed: i64,
status: &str,
) -> Result<()>
pub fn set_coverage( &self, repository_id: i64, files_seen: i64, files_indexed: i64, status: &str, ) -> Result<()>
Record indexing coverage for a repository (scope full).
Sourcepub fn set_file_git_ts(
&mut self,
repository_id: i64,
times: &HashMap<String, i64>,
) -> Result<()>
pub fn set_file_git_ts( &mut self, repository_id: i64, times: &HashMap<String, i64>, ) -> Result<()>
Set the last-commit time for files in a repository, from a path → unix-ts map (git log). Files not in the map are left untouched.
Sourcepub fn coverage_overview(&self) -> Result<Vec<CoverageRow>>
pub fn coverage_overview(&self) -> Result<Vec<CoverageRow>>
All known repositories with their coverage status and current totals.
Sourcepub fn identity_for_root(&self, root: &str) -> Result<Option<String>>
pub fn identity_for_root(&self, root: &str) -> Result<Option<String>>
The normalized identity of a repository by one of its checkout roots, if
known — lets the hot path resolve identity from the cache instead of
forking git remote. root should be the canonical work-tree path.
Sourcepub fn repository_id(&self, identity: &str) -> Result<Option<i64>>
pub fn repository_id(&self, identity: &str) -> Result<Option<i64>>
The id of a repository by its normalized identity, if known.
Sourcepub fn coverage_status(&self, identity: &str) -> Result<Option<String>>
pub fn coverage_status(&self, identity: &str) -> Result<Option<String>>
Coverage status for a repository’s full scope (never/warming/
complete), or None if the repository is unknown.
Sourcepub fn repo_totals(&self, repository_id: i64) -> Result<(i64, i64)>
pub fn repo_totals(&self, repository_id: i64) -> Result<(i64, i64)>
Current indexed totals for a repository: (files, symbols).
Sourcepub fn symbols_in_file(
&self,
repository_id: i64,
path: &str,
) -> Result<Vec<SymbolRow>>
pub fn symbols_in_file( &self, repository_id: i64, path: &str, ) -> Result<Vec<SymbolRow>>
Every symbol defined in one file (repo-relative path), in line order — a
structural outline rather than a ranked search. Backed by idx_symbols_file.
Sourcepub fn checkout_root(&self, repository_id: i64) -> Result<Option<String>>
pub fn checkout_root(&self, repository_id: i64) -> Result<Option<String>>
The on-disk root of a repository’s checkout, used to resolve relative paths when validating staleness.
Sourcepub fn checkout_roots(&self, repository_id: i64) -> Result<Vec<String>>
pub fn checkout_roots(&self, repository_id: i64) -> Result<Vec<String>>
Every checkout root recorded for a repository, newest first. A repo can have more than one (it was moved or cloned twice, both under the same remote identity), and an old row may be stale — so callers that read files try these in order (current checkout before a stale one).
Sourcepub fn forget_checkout(&mut self, root_path: &str) -> Result<()>
pub fn forget_checkout(&mut self, root_path: &str) -> Result<()>
Drop a checkout row — used to prune a stale binding (a repo moved away
from root_path). Symbols/coverage are keyed by repo identity, not this
row, so forgetting a checkout only forgets where the repo was on disk.
Sourcepub fn forget_file(&mut self, repository_id: i64, path: &str) -> Result<()>
pub fn forget_file(&mut self, repository_id: i64, path: &str) -> Result<()>
Drop a file and its symbols — used when a file has been deleted on disk.
Sourcepub fn drop_repository(&mut self, repository_id: i64) -> Result<()>
pub fn drop_repository(&mut self, repository_id: i64) -> Result<()>
Drop a repository entirely — the inverse of indexing it: its symbols (and their FTS rows, via trigger), files, coverage, learned selections, events, checkout, and the repository row. Deleted in FK-safe order in one transaction.
Sourcepub fn record_event(
&self,
kind: &str,
query: Option<&str>,
repository_id: Option<i64>,
path: Option<&str>,
line: Option<i64>,
branch: Option<&str>,
) -> Result<()>
pub fn record_event( &self, kind: &str, query: Option<&str>, repository_id: Option<i64>, path: Option<&str>, line: Option<i64>, branch: Option<&str>, ) -> Result<()>
Append a raw interaction event (the cheap write on the hot path; rollup
happens later in Store::aggregate_events).
Sourcepub fn selections_for(&self, query_norm: &str) -> Result<Vec<SelectionStat>>
pub fn selections_for(&self, query_norm: &str) -> Result<Vec<SelectionStat>>
Learned selections relevant to a query, read by ranking. Matches not just
the exact query but any shorter query the user has selected for — a pick
for han informs handler — so typing more keeps the benefit.
Sourcepub fn is_repeat_search(
&self,
repository_id: i64,
query_norm: &str,
) -> Result<bool>
pub fn is_repeat_search( &self, repository_id: i64, query_norm: &str, ) -> Result<bool>
Whether the most recent event for this repo is a search for the same
query — i.e. the query was repeated with no selection in between, a
signal that the last results missed.
Sourcepub fn decay_selections(
&self,
repository_id: i64,
query_norm: &str,
) -> Result<()>
pub fn decay_selections( &self, repository_id: i64, query_norm: &str, ) -> Result<()>
Decay the learned boost for a query — a repeated search signals the learned pick didn’t satisfy. Rows that reach zero are dropped.
Sourcepub fn aggregate_events(&mut self, batch: usize) -> Result<usize>
pub fn aggregate_events(&mut self, batch: usize) -> Result<usize>
Roll up to batch new open/select events into selection_stats.
Returns how many events were processed. Resolves the chosen symbol from
(repo, path, line) at rollup time, turning a selection into a
(query, file, name) signal. This is the amortized post-processing run
after a user interaction.
Sourcepub fn prune_events(&self, keep_recent: i64) -> Result<usize>
pub fn prune_events(&self, keep_recent: i64) -> Result<usize>
Keep the raw events log bounded. Deletes only events that have already
been rolled up (id ≤ the aggregation high-water mark) and are not among
the most recent keep_recent rows (which is_repeat_search needs).
Returns the number deleted.
Sourcepub fn indexed_head(&self, repository_id: i64) -> Result<Option<String>>
pub fn indexed_head(&self, repository_id: i64) -> Result<Option<String>>
The git HEAD sha recorded at the last complete index of a repo, if any — used to detect that the committed tree is unchanged since indexing.
Sourcepub fn set_indexed_head(&self, repository_id: i64, head: &str) -> Result<()>
pub fn set_indexed_head(&self, repository_id: i64, head: &str) -> Result<()>
Record the git HEAD sha at a complete index.
Sourcepub fn git_ts_head(&self, repository_id: i64) -> Result<Option<String>>
pub fn git_ts_head(&self, repository_id: i64) -> Result<Option<String>>
The git HEAD sha at the last commit-times capture (recency signal), if
any — lets the next capture read only the commits since, or skip the
git log entirely when HEAD hasn’t moved.
Sourcepub fn set_git_ts_head(&self, repository_id: i64, head: &str) -> Result<()>
pub fn set_git_ts_head(&self, repository_id: i64, head: &str) -> Result<()>
Record the git HEAD sha a commit-times capture ran at.
Sourcepub fn warm_lock(&self, identity: &str) -> Result<Option<(u32, i64)>>
pub fn warm_lock(&self, identity: &str) -> Result<Option<(u32, i64)>>
The detached-warm single-flight lock for a repo: (pid, stamped_at) of
the process that claimed it, if any. Liveness/staleness policy is the
caller’s (the store just holds the record).
Sourcepub fn set_warm_lock(&self, identity: &str, pid: u32) -> Result<()>
pub fn set_warm_lock(&self, identity: &str, pid: u32) -> Result<()>
Claim the detached-warm lock for this process.
Sourcepub fn clear_warm_lock(&self, identity: &str) -> Result<()>
pub fn clear_warm_lock(&self, identity: &str) -> Result<()>
Release the detached-warm lock.
Sourcepub fn branch_files_get(
&self,
identity: &str,
) -> Result<Option<(String, i64, Vec<String>)>>
pub fn branch_files_get( &self, identity: &str, ) -> Result<Option<(String, i64, Vec<String>)>>
The cached branch-changed file list for a repo: (stamp, computed_at, files). Stored rather than recomputed because the git diff behind it is
O(tracked files) and runs on the search path.
pub fn branch_files_set( &self, identity: &str, stamp: &str, at: i64, files: &[String], ) -> Result<()>
Sourcepub fn search_candidates(
&self,
query: &str,
limit: usize,
force_fuzzy: bool,
) -> Result<Vec<SymbolRow>>
pub fn search_candidates( &self, query: &str, limit: usize, force_fuzzy: bool, ) -> Result<Vec<SymbolRow>>
Candidate symbols for a query, drawn from cheap layers and merged:
exact/prefix on name_lower, then broad fuzzy recall (first-char anchor,
trigram FTS, path). Ranking happens in crate::search; this only narrows
the field.
When force_fuzzy is false and exact/prefix already matched, the broad
fuzzy layers are skipped: the relevance gate drops every fuzzy candidate
once a strong (exact/prefix) hit exists, so fetching and scoring them is
wasted. A wildcard query passes force_fuzzy = true — it isn’t gated and
always needs the trigram recall.