Skip to main content

Crate spg_embedded_tokio

Crate spg_embedded_tokio 

Source
Expand description

Tokio-friendly async wrapper around spg-embedded.

§Why this crate exists

spg-embedded’s Database::execute(&mut self, sql) is sync and may block on WAL fsync or cold-tier I/O. Called from inside a tokio::main runtime that triggers the block_in_place warning and ties up a worker thread until the call returns. mailrs’s cement (entirely tokio-based) is the load-bearing consumer that surfaced this.

v7.18 — AsyncDatabase holds a tokio::sync::RwLock<Database> (upgraded from Mutex). Writer calls take the write lock — the engine is still single-writer, that invariant hasn’t changed. Snapshot-taking (read_handle init / refresh) only needs read access to clone_snapshot, so it takes the read lock and concurrent snapshot refreshes do not serialise. spawn_blocking insulates the runtime’s worker pool from disk stalls the same way it did under Mutex.

§Why a separate crate

spg-embedded keeps the workspace’s “0 external dependencies” policy. tokio is the largest external dep we’d ever pull, and gating it behind a Cargo feature flag still surfaces tokio in downstream consumers’ Cargo.lock. A separate adapter crate is the clean answer: anyone who wants the tokio shape opts in by adding spg-embedded-tokio; everyone else stays untouched.

Structs§

AsyncDatabase
Tokio-friendly handle to an embedded SPG database. Clone-cheap (Arc inside); every clone shares the same underlying engine.
AsyncReadHandle
v7.11.2 — read-only handle backed by a frozen CatalogSnapshot. Multiple handles can run concurrently; they don’t acquire the writer lock at query time. Refresh-on-demand — the contract is that the handle reflects committed state at the moment of construction or the last refresh().
AsyncStatement
v7.16.0 — Tokio-flavoured prepared-statement handle. Wraps the sync spg_embedded::Statement in an Arc so the AST is shared (not cloned) across execute_prepared / query_prepared calls, and so the handle is Clone + Send without copying the AST per bind. The engine’s per-bind internal clone still happens — that’s where placeholder substitution lands — but the spg-embedded-tokio surface avoids the second clone the naive shape would force.
CatalogSnapshot
v7.11.0 — frozen read-only view of the engine’s committed state. Constructed via Engine::clone_snapshot. Holds clones of the catalog, statistics, clock function, and row-cap config — the four fields the execute_readonly path actually reads. Cheap to Clone (each clone shares the underlying PersistentVec row storage; only the trie root pointers copy). Send + Sync so a snapshot can be moved across tokio::task::spawn_blocking boundaries without coordination.
ColumnSchema
Database
Embedded SPG database handle. Owns an Engine + provides ergonomic wrappers around execute and query. Drops the engine on Drop — no WAL flush / fsync, because v6.10.3 is in-memory only.
Statement
v7.16.0 — handle for a parsed-and-planned SQL statement. Hand off to Database::execute_prepared / Database::query_prepared with a &[Value] slice carrying the bind parameters (PG-style $1, $2, … positional). Cheap to Clone; the underlying AST is shared by handle copies and cloned per bind call by the engine’s executor.

Enums§

DataType
Runtime type tags. Vector { dim, encoding } / Varchar(max) / Char(size) are parameterised; the parameter travels with both the column schema and the on-wire serialised representation.
EngineError
All errors the engine can return.
ParsedStatement
QueryResult
Result of executing one statement.
Value
A row-cell value, including SQL NULL. Float uses f64; NaN compares non-equal to itself (PG behaviour) — PartialEq is derived so callers must opt into NaN-aware comparison if they need stronger guarantees.