quiverdb-embed 0.24.0

The embeddable, in-process Quiver database handle.
Documentation

The embeddable, in-process Quiver database handle.

[Database] composes the storage engine ([quiver_core::Store]) with a per-collection vector index and payload filtering ([quiver_query::Filter]) into one handle. It exposes the same logical operations the server speaks (docs/api/wire-protocol.md), so library mode and server mode exercise identical engine semantics — the server is a thin transport/policy shell.

Index lifecycle

The store is the source of truth. Each collection chooses its index via the descriptor's [IndexSpec] (default in-memory HNSW); the index is built from the store on open. HNSW applies new-id inserts incrementally; once an IVF index is built it applies inserts, in-place updates, and deletes incrementally with LIRE rebalancing (ADR-0023). The Vamana / disk graph family is maintained the FreshDiskANN way (ADR-0033): the batch-built graph is a read-only base, recent inserts land in an in-memory delta graph, and deletes are tombstoned, so writes are size-independent; when the pending work grows past a fixed fraction of the base the next access consolidates by rebuilding from the store. All indexes stay derived (rebuilt from the store on open), so the crash gate never sees an index write.

Filtered (hybrid) search

A search may carry a [quiver_query::Filter] over the payload. The planner decomposes it into the predicates the collection's secondary indexes can answer; when those narrow the query to a small candidate set it scans that set exactly (perfect recall, no filtered-ANN cliff), and otherwise it over-fetches from the ANN index and post-filters. Both arms re-check the full filter, so results are exact regardless of which path runs.

Concurrency (ADR-0057 / ADR-0062)

Single-writer. Writes take &mut self. Reads come in two flavors: the &mut self convenience methods (search, hybrid_search, search_multi_vector) rebuild a stale index in place and so give embedded, single-threaded callers read-your-writes; the &self *_snapshot methods read the current immutable snapshot and run concurrently, serving the prior snapshot when a write deferred a rebuild (snapshot-isolated, slightly stale). A server therefore serves concurrent reads behind a reader–writer lock, and rebuilds off the exclusive lock (ADR-0062): it captures the rebuild inputs under the shared lock ([Database::snapshot_rebuild_inputs]), builds the new index with no lock held ([RebuildInputs::build]), and installs it under a brief write lock ([Database::commit_rebuild]) — so a rebuild never stalls concurrent readers.