Skip to main content

RocksDbStorageEngine

Struct RocksDbStorageEngine 

Source
pub struct RocksDbStorageEngine { /* private fields */ }

Implementations§

Source§

impl RocksDbStorageEngine

Source

pub fn open(path: impl AsRef<Path>) -> Result<Self>

Source

pub fn open_with_options( path: impl AsRef<Path>, opts: StorageOptions, ) -> Result<Self>

Open with operator-tunable rocksdb knobs. Applied to both the database-level options (FD cap, LOG retention) and every column family’s table options (bloom filter, write buffer). Defaults match RocksDbStorageEngine::open.

Source

pub fn put_node(&self, node: &Node) -> Result<()>

Source

pub fn get_node(&self, id: NodeId) -> Result<Option<Node>>

Source

pub fn put_edge(&self, edge: &Edge) -> Result<()>

Source

pub fn get_edge(&self, id: EdgeId) -> Result<Option<Edge>>

Source

pub fn delete_edge(&self, id: EdgeId) -> Result<()>

Source

pub fn detach_delete_node(&self, id: NodeId) -> Result<()>

Source

pub fn apply_batch(&self, mutations: &[GraphMutation]) -> Result<()>

Apply a sequence of mutations as one atomic rocksdb write. Either every mutation lands or none does — no replica can observe a partial result, even across a process crash.

Reads performed during batch construction (existing labels for PutNode, edge metadata for DeleteEdge / DetachDeleteNode) hit the live store, not the in-flight batch. Read-your-writes across mutations in the same batch is not supported. The executor never generates such patterns: it produces fresh ids per row and dedupes mutated entities before flushing.

Source

pub fn all_nodes(&self) -> Result<Vec<Node>>

Walk every node in the store. Used for snapshot construction; not suitable as a query primitive since it materializes the full set.

Source

pub fn all_edges(&self) -> Result<Vec<Edge>>

Walk every edge in the store. Used for snapshot construction.

Source

pub fn create_checkpoint(&self, path: impl AsRef<Path>) -> Result<()>

Produce a consistent point-in-time checkpoint of the store at path. Wraps rocksdb’s Checkpoint API — on the same filesystem the checkpoint is effectively free (hard links over the underlying SST files); cross-filesystem it falls back to a full copy. path must NOT already exist; rocksdb creates it.

Used by the Raft state machine’s streaming snapshot path: a snapshot is built by checkpointing into a temp dir, packing the checkpoint’s files into a length-prefixed archive, and shipping the bytes. Skips the “Vec in memory” materialization path that the previous JSON-over-everything snapshot used.

Source

pub fn clear_all(&self) -> Result<()>

Drop every key from every column family. Used by snapshot install to wipe local state before applying the leader’s snapshot. Cheap for empty / small stores; for large stores this is O(n).

Source

pub fn all_node_ids(&self) -> Result<Vec<NodeId>>

Source

pub fn outgoing(&self, source: NodeId) -> Result<Vec<(EdgeId, NodeId)>>

Source

pub fn incoming(&self, target: NodeId) -> Result<Vec<(EdgeId, NodeId)>>

Source

pub fn list_property_indexes(&self) -> Vec<PropertyIndexSpec>

Snapshot the currently-registered property indexes. Cheap clone — specs are tiny (a label + a property key).

Source

pub fn create_property_index(&self, label: &str, property: &str) -> Result<()>

Declare a new (label, property) single-property equality index and backfill it by scanning every node that currently carries label. Idempotent: re-creating an already-registered index is a no-op, matching how Neo4j’s CREATE INDEX IF NOT EXISTS behaves.

Backfill is done in the same WriteBatch as the meta insert, so a crash mid-backfill leaves the store with either zero entries (batch not yet written) or a fully-populated index (batch committed). No partial-build state is ever visible.

Source

pub fn create_property_index_composite( &self, label: &str, properties: &[String], ) -> Result<()>

Composite form of [create_property_index]. Declares a (label, properties) tuple index and backfills it by scanning every node currently carrying label. A node that’s missing any of the properties, or carries an unindexable value for any of them, contributes no entry — composite indexes are all-or-nothing on the tuple.

Single-property calls delegate here with a length-1 slice; the on-disk key format is byte-identical to the pre-composite layout in that case.

Source

pub fn create_property_constraint( &self, name: Option<&str>, scope: &ConstraintScope, properties: &[String], kind: PropertyConstraintKind, if_not_exists: bool, ) -> Result<PropertyConstraintSpec>

Declare a new property constraint. Behavior summary:

  • The name is the user-facing identifier. When name is None, a deterministic default (constraint_<label>_<prop>_<kind>) is generated so DROP CONSTRAINT can still target it.
  • If the chosen name is already registered with the same (label, property, kind), this is a no-op (the existing spec is returned). If the name collides on a different spec, returns ConstraintNameConflict unless if_not_exists is set, in which case the existing spec is preserved and returned unchanged.
  • UNIQUE constraints implicitly require a backing property index. create_property_constraint creates one on (label, property) if it isn’t already registered — matching Neo4j’s “a unique constraint also provides an index” contract.
  • Before committing, the method scans existing nodes to verify the constraint is satisfied. Any violation aborts the creation with ConstraintViolation; the registry is left unchanged.

The meta write and the implicit-index write are batched into a single WriteBatch so the on-disk state stays consistent under crash.

Source

pub fn drop_property_constraint( &self, name: &str, if_exists: bool, ) -> Result<()>

Tear down a constraint by name. When if_exists is true, dropping a non-existent constraint is a no-op. Never drops the backing index for UNIQUE — users who want it gone issue a separate DROP INDEX.

Source

pub fn list_property_constraints(&self) -> Vec<PropertyConstraintSpec>

Snapshot the currently-registered constraints. Cheap clone — every spec is a handful of small strings and an enum.

Source

pub fn drop_property_index(&self, label: &str, property: &str) -> Result<()>

Tear down a property index: removes the meta entry and every entry under the (label, prop) prefix. Idempotent: dropping a non-existent index is a no-op. Atomic via one WriteBatch.

Source

pub fn drop_property_index_composite( &self, label: &str, properties: &[String], ) -> Result<()>

Source

pub fn list_edge_property_indexes(&self) -> Vec<EdgePropertyIndexSpec>

Snapshot the currently-registered edge property indexes. Mirror of RocksDbStorageEngine::list_property_indexes for relationship scope. Cheap clone — specs are tiny.

Source

pub fn create_edge_property_index( &self, edge_type: &str, property: &str, ) -> Result<()>

Declare a new (edge_type, property) edge property index and backfill it by scanning every edge currently carrying edge_type. Idempotent: re-creating an already-registered index is a no-op. Mirror of RocksDbStorageEngine::create_property_index for relationship scope; the same “same WriteBatch” atomicity guarantee applies — a crash mid-backfill leaves the store with either zero entries or a fully-populated index, never a partially-built one.

Source

pub fn create_edge_property_index_composite( &self, edge_type: &str, properties: &[String], ) -> Result<()>

Source

pub fn drop_edge_property_index( &self, edge_type: &str, property: &str, ) -> Result<()>

Source

pub fn drop_edge_property_index_composite( &self, edge_type: &str, properties: &[String], ) -> Result<()>

Source

pub fn list_point_indexes(&self) -> Vec<PointIndexSpec>

Source

pub fn create_point_index(&self, label: &str, property: &str) -> Result<()>

Declare a new point index on (label, property) and backfill it by scanning every node that currently carries the label. Idempotent: re-creating a registered index is a no-op. Same “single WriteBatch” atomicity guarantee as the property-index create path — a crash mid-backfill leaves the store with either zero entries or a fully-populated index.

Source

pub fn drop_point_index(&self, label: &str, property: &str) -> Result<()>

Tear down a point index. Removes the meta entry and every entry under the <label>\0<prop>\0 prefix — that sweep covers all SRID variants at once, since SRID is to the right of the label+property header. Idempotent.

Source

pub fn nodes_in_bbox( &self, label: &str, property: &str, srid: i32, xlo: f64, ylo: f64, xhi: f64, yhi: f64, ) -> Result<Vec<NodeId>>

Range query: node ids whose indexed point falls inside the axis-aligned bounding box [(xlo, ylo), (xhi, yhi)] under srid. The scan walks the Morton-code cell range that covers the bbox and applies a precise per-row filter against the coordinates stored in the value — the cell range is a superset, so the filter is what guarantees correctness.

A missing index returns empty rather than erroring, matching the property-seek convention (lets the planner race a DROP without a fatal). Results are sorted by NodeId for determinism across runs.

Source

pub fn list_edge_point_indexes(&self) -> Vec<EdgePointIndexSpec>

Source

pub fn create_edge_point_index( &self, edge_type: &str, property: &str, ) -> Result<()>

Declare a new edge point index and backfill it by scanning every edge currently carrying edge_type. Idempotent. Single-property / relationship-scope analogue of RocksDbStorageEngine::create_point_index.

Source

pub fn drop_edge_point_index( &self, edge_type: &str, property: &str, ) -> Result<()>

Tear down an edge point index. Idempotent.

Source

pub fn edges_in_bbox( &self, edge_type: &str, property: &str, srid: i32, xlo: f64, ylo: f64, xhi: f64, yhi: f64, ) -> Result<Vec<EdgeId>>

Relationship-scope analogue of RocksDbStorageEngine::nodes_in_bbox. Same Z-order cell range + precise bbox filter via stored coords, just over CF_EDGE_POINT_INDEX.

Source

pub fn edges_by_property( &self, edge_type: &str, property: &str, value: &Property, ) -> Result<Vec<EdgeId>>

Look up edge ids for a (edge_type, property, value) equality via the edge-property-index CF. Mirror of RocksDbStorageEngine::nodes_by_property for relationship scope; unindexable value types surface as Error::UnindexableValue so callers can fall back to a type-wide scan rather than silently returning empty.

Source

pub fn edges_by_properties( &self, edge_type: &str, properties: &[String], values: &[Property], ) -> Result<Vec<EdgeId>>

Composite form of [edges_by_property]. Same contract as RocksDbStorageEngine::nodes_by_properties on the relationship side.

Source

pub fn nodes_by_property( &self, label: &str, property: &str, value: &Property, ) -> Result<Vec<NodeId>>

Look up node ids for a (label, property, value) equality via the property index CF. The caller is responsible for checking that the index exists first (e.g. the planner only emits IndexSeek when it has verified via RocksDbStorageEngine::list_property_indexes).

Unindexable value types (Float64, List, Map, Null) return Error::UnindexableValue — callers should surface this to the user rather than silently returning an empty result.

Source

pub fn nodes_by_properties( &self, label: &str, properties: &[String], values: &[Property], ) -> Result<Vec<NodeId>>

Composite form of [nodes_by_property]. Seeks every node whose (label, property_i = value_i) tuple matches in order. The two slices must have equal length. Unindexable value types surface as Error::UnindexableValue the same way the single-property form does — composite indexes are all-or-nothing and an unindexable slot can never match a stored tuple.

Source

pub fn nodes_by_label(&self, label: &str) -> Result<Vec<NodeId>>

Source

pub fn edges_by_type(&self, edge_type: &str) -> Result<Vec<EdgeId>>

Trait Implementations§

Source§

impl StorageEngine for RocksDbStorageEngine

Source§

fn put_node(&self, node: &Node) -> Result<()>

Source§

fn get_node(&self, id: NodeId) -> Result<Option<Node>>

Source§

fn detach_delete_node(&self, id: NodeId) -> Result<()>

Source§

fn put_edge(&self, edge: &Edge) -> Result<()>

Source§

fn get_edge(&self, id: EdgeId) -> Result<Option<Edge>>

Source§

fn delete_edge(&self, id: EdgeId) -> Result<()>

Source§

fn apply_batch(&self, mutations: &[GraphMutation]) -> Result<()>

Apply a sequence of mutations atomically. Either every mutation lands or none does. See GraphMutation for the variant set.
Source§

fn all_nodes(&self) -> Result<Vec<Node>>

Source§

fn all_edges(&self) -> Result<Vec<Edge>>

Source§

fn all_node_ids(&self) -> Result<Vec<NodeId>>

Source§

fn outgoing(&self, source: NodeId) -> Result<Vec<(EdgeId, NodeId)>>

Source§

fn incoming(&self, target: NodeId) -> Result<Vec<(EdgeId, NodeId)>>

Source§

fn nodes_by_label(&self, label: &str) -> Result<Vec<NodeId>>

Source§

fn edges_by_type(&self, edge_type: &str) -> Result<Vec<EdgeId>>

Source§

fn nodes_by_property( &self, label: &str, property: &str, value: &Property, ) -> Result<Vec<NodeId>>

Source§

fn nodes_by_properties( &self, label: &str, properties: &[String], values: &[Property], ) -> Result<Vec<NodeId>>

Composite form of Self::nodes_by_property. properties and values are parallel slices of equal length — the tuple must match an equivalent stored index entry. Single-property callers should use Self::nodes_by_property which delegates here with length-1 slices.
Source§

fn edges_by_property( &self, edge_type: &str, property: &str, value: &Property, ) -> Result<Vec<EdgeId>>

Equality lookup through an edge property index. Mirrors StorageEngine::nodes_by_property for the relationship side. The caller is responsible for verifying the (edge_type, property) index exists before dispatching — a missing index returns an empty result (no entries maintained) rather than erroring so the planner’s race with a concurrent DROP stays safe.
Source§

fn create_property_index(&self, label: &str, property: &str) -> Result<()>

Source§

fn drop_property_index(&self, label: &str, property: &str) -> Result<()>

Source§

fn create_property_index_composite( &self, label: &str, properties: &[String], ) -> Result<()>

Composite form of Self::create_property_index — declares a tuple index over (label, properties...). Single-property callers should use Self::create_property_index which delegates here with a length-1 slice.
Source§

fn drop_property_index_composite( &self, label: &str, properties: &[String], ) -> Result<()>

Composite form of Self::drop_property_index.
Source§

fn list_property_indexes(&self) -> Vec<PropertyIndexSpec>

Source§

fn create_edge_property_index( &self, edge_type: &str, property: &str, ) -> Result<()>

Declare a new (edge_type, property) single-property equality index and backfill it from every edge currently carrying the type. Idempotent: re-creating an already-registered index is a no-op. Matches StorageEngine::create_property_index for node scope.
Source§

fn drop_edge_property_index( &self, edge_type: &str, property: &str, ) -> Result<()>

Tear down an edge property index. Removes the meta entry and every entry under the (edge_type, prop) prefix. Idempotent.
Source§

fn create_edge_property_index_composite( &self, edge_type: &str, properties: &[String], ) -> Result<()>

Source§

fn drop_edge_property_index_composite( &self, edge_type: &str, properties: &[String], ) -> Result<()>

Source§

fn list_edge_property_indexes(&self) -> Vec<EdgePropertyIndexSpec>

Snapshot the currently-registered edge property indexes.
Source§

fn create_point_index(&self, label: &str, property: &str) -> Result<()>

Declare a point index on (label, property) and backfill it by scanning every node carrying label. Idempotent: re-creating a registered index is a no-op. Single-property and node-scope only — composite / relationship-scope spatial indexes are follow-ups.
Source§

fn drop_point_index(&self, label: &str, property: &str) -> Result<()>

Tear down a point index. Removes the meta entry and sweeps every stored entry under the (label, property) header — the SRID-keyed sub-prefixes all fall inside that header, so one range scan covers all coordinate systems. Idempotent.
Source§

fn list_point_indexes(&self) -> Vec<PointIndexSpec>

Snapshot the currently-registered point indexes.
Source§

fn nodes_in_bbox( &self, label: &str, property: &str, srid: i32, xlo: f64, ylo: f64, xhi: f64, yhi: f64, ) -> Result<Vec<NodeId>>

Axis-aligned bounding-box range query over the point index (label, property) under srid. Entries tagged with a different SRID are scoped out by the index key prefix, so cross-SRID rows never leak. A missing index returns empty rather than erroring — matches the soft-fail contract of Self::nodes_by_property.
Source§

fn create_edge_point_index(&self, edge_type: &str, property: &str) -> Result<()>

Relationship-scope analogue of Self::create_point_index. Declares an edge point index on (edge_type, property) and backfills by scanning every edge currently carrying edge_type. Idempotent.
Source§

fn drop_edge_point_index(&self, edge_type: &str, property: &str) -> Result<()>

Tear down an edge point index. Idempotent. Mirrors Self::drop_point_index.
Source§

fn list_edge_point_indexes(&self) -> Vec<EdgePointIndexSpec>

Snapshot the currently-registered edge point indexes.
Source§

fn edges_in_bbox( &self, edge_type: &str, property: &str, srid: i32, xlo: f64, ylo: f64, xhi: f64, yhi: f64, ) -> Result<Vec<EdgeId>>

Relationship-scope analogue of Self::nodes_in_bbox.
Source§

fn create_property_constraint( &self, name: Option<&str>, scope: &ConstraintScope, properties: &[String], kind: PropertyConstraintKind, if_not_exists: bool, ) -> Result<PropertyConstraintSpec>

Declare a new property constraint. If name is None, the backend derives a deterministic name from the other fields so DROP CONSTRAINT can still target it. When if_not_exists is true, re-declaring a constraint with the same name is a no-op (including when the existing constraint has different label/property/kind — matches Neo4j’s name-first semantics). Returns the final PropertyConstraintSpec that was either installed or already present. Read more
Source§

fn drop_property_constraint(&self, name: &str, if_exists: bool) -> Result<()>

Tear down a constraint identified by name. When if_exists is true, dropping a non-existent constraint is a no-op.
Source§

fn list_property_constraints(&self) -> Vec<PropertyConstraintSpec>

Snapshot every registered constraint. Order is insertion order for deterministic SHOW CONSTRAINTS output across restarts.
Source§

fn put_trigger(&self, name: &str, value: &[u8]) -> Result<()>

Persist an apoc.trigger.* registration. The value is a JSON-encoded blob owned by meshdb-executor’s TriggerSpec — storage stays format-agnostic so the schema can evolve without bumping the storage trait. Default impl errors loudly so backends that haven’t wired triggers in yet surface the gap immediately.
Source§

fn delete_trigger(&self, name: &str) -> Result<()>

Remove a registered trigger by name. Idempotent — dropping a non-existent name is a no-op.
Source§

fn list_triggers(&self) -> Result<Vec<(String, Vec<u8>)>>

Snapshot every registered trigger as (name, value) pairs in insertion-order by name. The value bytes are passed straight back to the caller for format-side decoding.
Source§

fn put_pending_tx(&self, key: &[u8], value: &[u8]) -> Result<()>

Persist an in-doubt cross-partition transaction’s staging blob. Used by the multi-raft PartitionGraphApplier so pending_txs survives a process restart — without persistence, an applied PreparedTx would be invisible to post-restart recovery (openraft replays only entries past last_applied, and the staged commands live in memory). Read more
Source§

fn delete_pending_tx(&self, key: &[u8]) -> Result<()>

Drop a pending-tx entry by key. Idempotent for unknown keys.
Source§

fn list_pending_txs(&self) -> Result<Vec<(Vec<u8>, Vec<u8>)>>

All pending-tx entries as (key, value) pairs. The applier scans this on startup to rebuild its in-memory map.
Source§

fn create_checkpoint(&self, path: &Path) -> Result<()>

Persist a point-in-time copy of the backend’s on-disk state into path. The shape of what lands at path is backend-specific — the caller is expected to package it in a backend-aware way (see meshdb-rpc::raft_applier for the RocksDB path). For RocksDB this is a Checkpoint directory of SST files; a different backend is free to write a single file, a directory of segments, etc., as long as its own open(path) can later rehydrate from the same layout.
Source§

fn clear_all(&self) -> Result<()>

Drop every entry from every part of the backend. Used by the Raft snapshot-install path to wipe local state before applying the leader’s snapshot.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.