pub struct Database<S> { /* private fields */ }Expand description
Owns the graph store and orchestrates parse → analyze → compile → execute.
Optionally drives a write-ahead log: when constructed via
Database::open_with_wal or Database::recover the database
holds an Arc<WalRecorder> that brackets every query with
begin → mutations → commit/abort → flush while the engine mutex
is held, so the WAL order is exactly the in-memory commit order.
When constructed via Database::in_memory / Database::from_graph
the WAL handle is None and the engine pays only the existing
MutationRecorder::record null-pointer check per mutation.
Implementations§
Source§impl Database<InMemoryGraph>
impl Database<InMemoryGraph>
Sourcepub fn open_with_wal(wal_config: WalConfig) -> Result<Self>
pub fn open_with_wal(wal_config: WalConfig) -> Result<Self>
Open or create a WAL-enabled in-memory database from a fresh graph.
WalConfig::Disabled falls back to Database::in_memory.
Otherwise, opens the WAL directory, replays any committed
events into a fresh graph, installs a WalRecorder on the
graph, and returns a database ready to serve queries.
To restore from a snapshot in addition to the WAL, use
Database::recover instead.
Sourcepub fn recover(
snapshot_path: impl AsRef<Path>,
wal_config: WalConfig,
) -> Result<Self>
pub fn recover( snapshot_path: impl AsRef<Path>, wal_config: WalConfig, ) -> Result<Self>
Restore from a snapshot file then replay any WAL records past it.
The snapshot’s wal_lsn (when set) becomes the replay fence —
events at or below that LSN are already represented in the
loaded snapshot and are skipped. A missing snapshot file is
treated as “fresh start” so operators can pass the same path
on every boot.
If the WAL contains a checkpoint marker newer than the
snapshot’s wal_lsn, a one-line warning is printed to stderr
— the snapshot is stale relative to a more recent checkpoint
the operator is presumably aware of. Recovery still proceeds
from the snapshot’s fence (replay re-applies every record
above it, which is conservative-correct); a tighter contract
is deferred to v2 because verifying that the marker’s
snapshot file actually exists and is loadable is a separate
observability concern.
Source§impl<S> Database<S>where
S: GraphStorage + GraphStorageMut,
impl<S> Database<S>where
S: GraphStorage + GraphStorageMut,
Sourcepub fn from_graph(graph: S) -> Self
pub fn from_graph(graph: S) -> Self
Build a database by taking ownership of a bare graph store.
Sourcepub fn wal(&self) -> Option<&Arc<WalRecorder>>
pub fn wal(&self) -> Option<&Arc<WalRecorder>>
Handle to the installed WAL recorder, if any. Exposed for admin paths (checkpoint, truncate, observability) that need to drive the WAL outside the standard query lifecycle.
Sourcepub fn store(&self) -> &Arc<Mutex<S>>
pub fn store(&self) -> &Arc<Mutex<S>>
Handle to the underlying shared store — useful for callers that need to snapshot or share the graph across multiple databases.
Sourcepub fn parse(&self, query: &str) -> Result<Document>
pub fn parse(&self, query: &str) -> Result<Document>
Parse a query string into an AST without executing it.
Sourcepub fn execute(
&self,
query: &str,
options: Option<ExecuteOptions>,
) -> Result<QueryResult>
pub fn execute( &self, query: &str, options: Option<ExecuteOptions>, ) -> Result<QueryResult>
Execute a query and return its result.
Sourcepub fn execute_with_params(
&self,
query: &str,
options: Option<ExecuteOptions>,
params: BTreeMap<String, LoraValue>,
) -> Result<QueryResult>
pub fn execute_with_params( &self, query: &str, options: Option<ExecuteOptions>, params: BTreeMap<String, LoraValue>, ) -> Result<QueryResult>
Execute a query with bound parameters.
When a WAL is attached the call is bracketed by a transaction:
recorder.arm()after analyze + compile (so a parse / semantic / compile error never opens a tx that has to be immediately aborted). Arming is cheap: no record is appended to the WAL yet, so a pure read query that completes here pays nothing for the WAL hot path.- The executor runs; every primitive mutation fires
MutationRecorder::record, which on its first call lazily issuesWal::beginand from then on forwards every event toWal::append. - On Ok,
recorder.commit()writes aTxCommitonly when aTxBeginwas actually allocated; the surroundingrecorder.flush()runs only in that case so a read-only query never pays anfsync. - On Err,
recorder.abort()marks the (lazily-issued) tx for replay-time discard; if noTxBeginwas issued, abort is a no-op on the WAL. The engine has no rollback, so the in-memory state may already be partially mutated; the abort marker is what gives the durable layer per-query atomicity. - The recorder’s poisoned flag is polled once (it also
surfaces background-flusher fsync failures from
SyncMode::Group). If set, the query fails loudly with the durability error so the caller can act on it; the WAL refuses further appends until the operator restarts the database, which recovers from the last consistent snapshot + WAL.
Sourcepub fn clear(&self)
pub fn clear(&self)
Drop every node and relationship.
When a WAL is attached, clear() is wrapped in arm/commit
so the MutationEvent::Clear fired by the store reaches the
log inside a transaction (without arming, the recorder would
poison itself on the first event). WAL failures here are
best-effort: the in-memory state is still cleared so the
caller’s contract holds, but the recorder’s poisoned flag
will surface to the next query.
Sourcepub fn node_count(&self) -> usize
pub fn node_count(&self) -> usize
Number of nodes currently in the graph.
Sourcepub fn relationship_count(&self) -> usize
pub fn relationship_count(&self) -> usize
Number of relationships currently in the graph.
Sourcepub fn with_store<R>(&self, f: impl FnOnce(&S) -> R) -> R
pub fn with_store<R>(&self, f: impl FnOnce(&S) -> R) -> R
Run a closure with a shared borrow of the underlying store. Used by bindings to answer ad-hoc queries without locking the mutex themselves.
Sourcepub fn with_store_mut<R>(&self, f: impl FnOnce(&mut S) -> R) -> R
pub fn with_store_mut<R>(&self, f: impl FnOnce(&mut S) -> R) -> R
Run a closure with an exclusive borrow of the underlying store. Reserved
for admin paths (restore, bulk load); regular mutation goes through
execute_with_params.
Source§impl<S> Database<S>
impl<S> Database<S>
Sourcepub fn save_snapshot_to(&self, path: impl AsRef<Path>) -> Result<SnapshotMeta>
pub fn save_snapshot_to(&self, path: impl AsRef<Path>) -> Result<SnapshotMeta>
Serialize the current graph state to the given path. Writes are
atomic: the payload goes to <path>.tmp, is fsync’d, and then
renamed over the target; a torn write can never leave a half-written
file at path. If any step before the rename fails, the stale
<path>.tmp is removed so a crashed save never leaks scratch files.
Holds the store mutex for the duration of the save so concurrent queries see a consistent point-in-time snapshot.
Sourcepub fn load_snapshot_from(&self, path: impl AsRef<Path>) -> Result<SnapshotMeta>
pub fn load_snapshot_from(&self, path: impl AsRef<Path>) -> Result<SnapshotMeta>
Replace the current graph state with a snapshot loaded from path.
Holds the store mutex for the duration of the load; concurrent
queries block until restore completes.
Source§impl Database<InMemoryGraph>
impl Database<InMemoryGraph>
Sourcepub fn in_memory_from_snapshot(path: impl AsRef<Path>) -> Result<Self>
pub fn in_memory_from_snapshot(path: impl AsRef<Path>) -> Result<Self>
Convenience constructor: open (or create) an empty in-memory database
and immediately restore it from path. Errors if the file cannot be
opened or the snapshot is malformed.
Sourcepub fn checkpoint_to(&self, path: impl AsRef<Path>) -> Result<SnapshotMeta>
pub fn checkpoint_to(&self, path: impl AsRef<Path>) -> Result<SnapshotMeta>
Take a checkpoint: snapshot the current state with the WAL’s
durable_lsn stamped into the header, append a Checkpoint
marker to the WAL, then drop sealed segments at or below the
fence.
Errors with “checkpoint requires WAL enabled” when called on a
database constructed without a WAL — operators that just want
a fence-less dump should use [save_snapshot_to] instead.
The mutex-held window covers snapshot serialization plus the
checkpoint marker append. Truncation runs after the rename
but still under the mutex; making it concurrent with queries
is a v2 concern (see docs/decisions/0004-wal.md).
Trait Implementations§
Source§impl<S> QueryRunner for Database<S>
impl<S> QueryRunner for Database<S>
fn execute( &self, query: &str, options: Option<ExecuteOptions>, ) -> Result<QueryResult>
Source§impl<S> SnapshotAdmin for Database<S>
impl<S> SnapshotAdmin for Database<S>
fn save_snapshot(&self, path: &Path) -> Result<SnapshotMeta>
fn load_snapshot(&self, path: &Path) -> Result<SnapshotMeta>
Source§impl WalAdmin for Database<InMemoryGraph>
impl WalAdmin for Database<InMemoryGraph>
Source§fn checkpoint(&self, path: &Path) -> Result<SnapshotMeta>
fn checkpoint(&self, path: &Path) -> Result<SnapshotMeta>
path. The snapshot’s header is stamped
with the WAL’s durable_lsn; older sealed segments are then
dropped.