How it works
Persia is a library you open on a file, plus a server that embeds the same engine.
That library shape is an embedded search database: full-text search in the application process, stored in a file.
The engine is synchronous. It talks to disks and object storage only through the Storage trait.
Async belongs in the cloud backends and in the server. Memory and local-file backends exist.
S3, GCS, and Azure do not.
╔═ layers ═════════════════════════════════════════════════════════╗ ║ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ║░ ║ ┃ persia-server, Rust SDK, Go SDK ┃ ║░ ║ ┃ planned ┃ ║░ ║ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ║░ ║ ▼ ║░ ║ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ║░ ║ ┃ persia · Db and Collection ┃ ║░ ║ ┃ stub · no methods yet ┃ ║░ ║ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ║░ ║ ▼ ║░ ║ ┏━━━━━━━━━━━━━━━━━━┓ ┏━━━━━━━━━━━━━━━━━━┓ ┏━━━━━━━━━━━━━━━━━━┓ ║░ ║ ┃ engine ┃ ┃ blob ┃ ┃ analysis ┃ ║░ ║ ┃ WAL and query ┃ ┃ chunks, dedup ┃ ┃ analyzers ┃ ║░ ║ ┃ in progress ┃ ┃ not started ┃ ┃ done ┃ ║░ ║ ┗━━━━━━━━━━━━━━━━━━┛ ┗━━━━━━━━━━━━━━━━━━┛ ┗━━━━━━━━━━━━━━━━━━┛ ║░ ║ ▼ ║░ ║ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ║░ ║ ┃ persia-storage ┃ ║░ ║ ┃ memory and local file ┃ ║░ ║ ┃ s3, gcs, azure planned ┃ ║░ ║ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ║░ ║ ▼ ║░ ║ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ║░ ║ ┃ persia-format ┃ ║░ ║ ┃ encodings, checksums, codecs ┃ ║░ ║ ┃ done ┃ ║░ ║ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ║░ ╚══════════════════════════════════════════════════════════════════╝░ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
A write
Section titled “A write”╔═ write ══════════════════════════════════════════════════════════╗ ║ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ║░ ║ ┃ 1. put or delete ┃ ║░ ║ ┃ WAL, then memtable ┃ ║░ ║ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ║░ ║ ▼ ║░ ║ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ║░ ║ ┃ 2. flush ┃ ║░ ║ ┃ memtable becomes a segment ┃ ║░ ║ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ║░ ║ ▼ ║░ ║ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ║░ ║ ┃ 3. commit ┃ ║░ ║ ┃ data, then manifest, then ┃ ║░ ║ ┃ the inactive superblock ┃ ║░ ║ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ║░ ║ ▼ ║░ ║ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ║░ ║ ┃ 4. merge, later ┃ ║░ ║ ┃ new segment, new manifest ┃ ║░ ║ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ║░ ╚══════════════════════════════════════════════════════════════════╝░ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
A query
Section titled “A query”╔═ query ══════════════════════════════════════════════════════════╗ ║ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ║░ ║ ┃ 1. analyze the text ┃ ║░ ║ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ║░ ║ ▼ ║░ ║ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ║░ ║ ┃ 2. each segment ┃ ║░ ║ ┃ and the memtable ┃ ║░ ║ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ║░ ║ ▼ ║░ ║ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ║░ ║ ┃ 3. merge the top hits ┃ ║░ ║ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ║░ ║ ▼ ║░ ║ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ║░ ║ ┃ 4. too few hits? ┃ ║░ ║ ┃ no: return them ┃ ║░ ║ ┃ yes: relax ┃ ║░ ║ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ║░ ║ ▼ ║░ ║ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ║░ ║ ┃ 5. cascade, L0 to L5 ┃ ║░ ║ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ║░ ╚══════════════════════════════════════════════════════════════════╝░ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
The compiler and the BM25F scorer are in the tree. Searching segments and the relaxation cascade are not. Typo-tolerant search is the longer account.
Storage and segments
Section titled “Storage and segments”A segment is one byte string: sections, then a footer. Locally it is a frame payload. Remotely it is
one object. The bytes match. Codecs on a block are None and Zstd. The local container, the block
codecs, and the memory and file backends exist. persia-engine implements collection schema, documents, and manifests (M3 done, 15/15) and a segment builder, writer, and reader (M5 done, 48/48). Its write path is in progress (M6, 49/58): a memtable, a WAL with chunks, group commit, and replay, flush, commit, snapshots, auto-commit, and open checks, deletes and upserts across segments with tombstone sidecars, and segment merging (a merge policy, a segment merger, a background scheduler, and deletion of obsolete objects). Its query path is in progress (M7, 46/51): a query AST, user-text compiler, filter DSL, and query limits, collection statistics (document count, document frequency, average field length), BM25F scoring with static rank and score bounds, matching and score top-k over one view, and a collection search with sorts, pages, facets, and stored fields (CollectionViews::search). Relaxation has not been started (M8). A collection snapshot can be searched as library code. There is no search call on the database handle.
S3, GCS, and Azure backends do not (M12).
╔═ storage ════════════════════════════════════════════════════════╗ ║ local file object storage ║░ ║ ┏━━━━━━━━━━━━━━━━━━━━━━┓ ┏━━━━━━━━━━━━━━━━━━━━━━┓ ║░ ║ ┃ header, 12 KiB ┃ same bytes ┃ manifests/seq ┃ ║░ ║ ┃ two superblocks ┃ ┃ segments/... ┃ ║░ ║ ┃ append-only frames ┃ ┃ blobs/... ┃ ║░ ║ ┗━━━━━━━━━━━━━━━━━━━━━━┛ ┗━━━━━━━━━━━━━━━━━━━━━━┛ ║░ ║ ▼ ║░ ║ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ║░ ║ ┃ sections, then sections ┃ ║░ ║ ┃ footer: stats, table, CRC ┃ ║░ ║ ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ ║░ ║ 16 KiB blocks · codec None or Zstd ║░ ╚══════════════════════════════════════════════════════════════════╝░ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
The contributor map, with the crate dependency graph, is docs/architecture.md. Quotes from the code that exists today are on the code page.