Skip to main content

MemoryStore

Trait MemoryStore 

Source
pub trait MemoryStore {
Show 21 methods // Required methods fn store( &self, id: u64, content: &str, embedding: &[f32], ) -> Result<(), MemoryError>; fn store_with_metadata( &self, id: u64, content: &str, embedding: &[f32], metadata: &Metadata, ) -> Result<(), MemoryError>; fn store_with_ttl( &self, id: u64, content: &str, embedding: &[f32], ttl_seconds: u64, ) -> Result<(), MemoryError>; fn update_metadata( &self, id: u64, metadata: &Metadata, ) -> Result<(), MemoryError>; fn get(&self, id: u64) -> Result<Option<(String, Vec<f32>)>, MemoryError>; fn get_metadata(&self, id: u64) -> Result<Option<Metadata>, MemoryError>; fn get_metadata_batch( &self, ids: &[u64], ) -> Result<Vec<Option<Metadata>>, MemoryError>; fn delete(&self, id: u64) -> Result<(), MemoryError>; fn query_filtered( &self, embedding: &[f32], k: usize, filter: &Metadata, offset: usize, ) -> Result<Vec<(u64, f32, String)>, MemoryError>; fn query_excluding( &self, embedding: &[f32], k: usize, exclude: &Metadata, ) -> Result<Vec<(u64, f32, String)>, MemoryError>; fn query_columnar( &self, embedding: &[f32], k: usize, filters: &[ColumnFilter], ) -> Result<Vec<Recollection>, MemoryError>; fn relate( &self, from: u64, to: u64, relation: &str, ) -> Result<u64, MemoryError>; fn relations(&self, id: u64) -> Result<Vec<MemoryEdge>, MemoryError>; fn incoming_relations( &self, id: u64, ) -> Result<Vec<MemoryEdge>, MemoryError>; fn relations_bounded( &self, id: u64, cap: usize, ) -> Result<BoundedMemoryEdges, MemoryError>; fn incoming_relations_bounded( &self, id: u64, cap: usize, ) -> Result<BoundedMemoryEdges, MemoryError>; fn unrelate(&self, edge_id: u64) -> Result<bool, MemoryError>; fn count(&self) -> usize; // Provided methods fn store_with_metadata_and_ttl( &self, id: u64, content: &str, embedding: &[f32], metadata: &Metadata, ttl_seconds: u64, ) -> Result<(), MemoryError> { ... } fn edge_count(&self) -> Option<usize> { ... } fn list( &self, cursor: Option<u64>, limit: usize, ) -> Result<(Vec<RawListedFact>, Option<u64>), MemoryError> { ... }
}
Expand description

The storage primitives crate::service::MemoryService needs: write, vector search, graph edges, and by-id lookup. A backend that implements this trait can run the full wedge (remember/recall/recall_fused/ relate/forget/why/remember_extracted) with no orchestration code duplicated.

Required Methods§

Source

fn store( &self, id: u64, content: &str, embedding: &[f32], ) -> Result<(), MemoryError>

Store a fact with no metadata or expiry.

§Errors

Returns MemoryError if persistence fails.

Source

fn store_with_metadata( &self, id: u64, content: &str, embedding: &[f32], metadata: &Metadata, ) -> Result<(), MemoryError>

Store a fact tagged with metadata, no expiry.

§Errors

Returns MemoryError if persistence fails.

Source

fn store_with_ttl( &self, id: u64, content: &str, embedding: &[f32], ttl_seconds: u64, ) -> Result<(), MemoryError>

Store a fact that expires after ttl_seconds, no metadata.

§Errors

Returns MemoryError if persistence fails.

Source

fn update_metadata( &self, id: u64, metadata: &Metadata, ) -> Result<(), MemoryError>

Merge metadata into an already-stored fact’s payload, preserving any durable TTL. Used to combine metadata with an expiry (store both in two calls rather than needing every metadata×TTL combination as a separate primitive).

§Errors

Returns MemoryError if id is unknown or persistence fails.

Source

fn get(&self, id: u64) -> Result<Option<(String, Vec<f32>)>, MemoryError>

A fact’s content and embedding, or None if unknown/expired.

§Errors

Returns MemoryError if storage access fails.

Source

fn get_metadata(&self, id: u64) -> Result<Option<Metadata>, MemoryError>

A fact’s raw stored payload — reserved system keys (_veles_*) included, so the service layer can check the hub flag before stripping them for the caller — or None when the fact is unknown/expired.

§Errors

Returns MemoryError if storage access fails.

Source

fn get_metadata_batch( &self, ids: &[u64], ) -> Result<Vec<Option<Metadata>>, MemoryError>

Batched Self::get_metadata: one storage round trip for every id in ids, results in the same order and length (an unknown or expired id maps to None). Same raw-payload semantics as the single-id form.

§Errors

Returns MemoryError if storage access fails.

Source

fn delete(&self, id: u64) -> Result<(), MemoryError>

Delete a fact.

§Errors

Returns MemoryError if deletion fails.

Source

fn query_filtered( &self, embedding: &[f32], k: usize, filter: &Metadata, offset: usize, ) -> Result<Vec<(u64, f32, String)>, MemoryError>

Vector search for up to k ids, narrowed to facts whose metadata exactly matches every key in filter.

§Errors

Returns MemoryError if the query fails.

Source

fn query_excluding( &self, embedding: &[f32], k: usize, exclude: &Metadata, ) -> Result<Vec<(u64, f32, String)>, MemoryError>

Vector search for up to k ids, dropping facts whose metadata matches every key in exclude.

§Errors

Returns MemoryError if the query fails.

Source

fn query_columnar( &self, embedding: &[f32], k: usize, filters: &[ColumnFilter], ) -> Result<Vec<Recollection>, MemoryError>

Vector search fused with structured ColumnStore predicates (ranges and comparisons, not just equality) — the engine behind crate::service::MemoryService::recall_where.

§Absent and null fields

A filter is satisfied only by a fact that HAS the field with a non-null value. A fact missing the field, or storing null in it, is never returned — and ne is no exception, exactly as a SQL comparison against NULL is never true.

field statefield != targetfield == target< <= > >=
absentno matchno matchno match
present, nullno matchno matchno match
present, equalno matchmatchper the comparison
present, differentmatchno matchper the comparison

This is stated because it did not hold: ne on an absent field matched on the native backend and never matched on WASM, for the API’s whole life, because nothing compared them (#1759). Every backend is now held to one shared table — crate::column_filter_conformance — run against both.

Null-ness is not expressible through ColumnFilter; querying for it is what IsNull/IsNotNull are for at the VelesQL layer.

§Errors

Returns MemoryError::InvalidFilter if a filter field is not a plain identifier or a filter value is non-scalar, or MemoryError if the query fails.

Source

fn relate(&self, from: u64, to: u64, relation: &str) -> Result<u64, MemoryError>

Create a typed edge from -> to. Returns the edge id.

§Errors

Returns MemoryError if either endpoint is missing or persistence fails.

Source

fn relations(&self, id: u64) -> Result<Vec<MemoryEdge>, MemoryError>

The outgoing edges of id.

§Errors

Returns MemoryError if storage access fails.

Source

fn incoming_relations(&self, id: u64) -> Result<Vec<MemoryEdge>, MemoryError>

The incoming edges of id — the mirror of Self::relations, with the same liveness rule applied to the far end (here the source).

§Errors

Returns MemoryError if storage access fails.

Source

fn relations_bounded( &self, id: u64, cap: usize, ) -> Result<BoundedMemoryEdges, MemoryError>

At most cap outgoing edges of id, plus whether its total degree exceeded the scan — the bounded twin of Self::relations (#1820).

The contract is on COST, not just shape: an implementation must keep work and transient allocation O(cap), never O(degree) — a super-node (an entity hub mentioned by thousands of facts) is exactly where this accessor is reached for. truncated is a separate signal because edges.len() == cap cannot carry it: a node with exactly cap edges is indistinguishable from a truncated one.

§Errors

Returns MemoryError if storage access fails.

Source

fn incoming_relations_bounded( &self, id: u64, cap: usize, ) -> Result<BoundedMemoryEdges, MemoryError>

At most cap incoming edges of id, plus whether its total incoming degree exceeded the scan — the mirror of Self::relations_bounded, same O(cap) cost contract.

§Errors

Returns MemoryError if storage access fails.

Source

fn unrelate(&self, edge_id: u64) -> Result<bool, MemoryError>

Remove the edge with edge_id. Returns true when it existed — idempotent: removing an absent edge is Ok(false), never an error.

§Errors

Returns MemoryError if storage access fails.

Source

fn count(&self) -> usize

The total number of live (non-expired) tracked facts, including internal entity hubs — used as a corpus-size proxy for idf weighting.

Provided Methods§

Source

fn store_with_metadata_and_ttl( &self, id: u64, content: &str, embedding: &[f32], metadata: &Metadata, ttl_seconds: u64, ) -> Result<(), MemoryError>

Store a fact with BOTH metadata and a durable TTL, in ONE write.

Default: the historical two-call sequence, so a backend written before this method keeps compiling and behaving as it did. Backends that can write both at once should override it — the two-call form leaves the fact live and expiring between the calls, so a short TTL can lapse in the gap and the metadata write then fails on a fact that was perfectly valid when the caller asked for it.

§Errors

Returns MemoryError if persistence fails.

Source

fn edge_count(&self) -> Option<usize>

The total number of graph edges, when the backend can answer without materializing them — the observable difference between a store whose why() can walk somewhere and one where it degrades to plain similarity search.

Defaulted to None (“cannot say”) rather than required, deliberately: a backend outside this crate (velesdb-wasm’s in-memory store) must keep compiling when this surface grows, and a wrong-but-cheap answer here would flag healthy graphs as flat. memory_status reports the distinction to the caller instead of papering over it.

Source

fn list( &self, cursor: Option<u64>, limit: usize, ) -> Result<(Vec<RawListedFact>, Option<u64>), MemoryError>

One cursor page of the store’s live facts, ids ascending: up to limit entries strictly after cursor (None starts the walk), plus the cursor for the next page (None ends it). Payloads come back RAW — reserved keys and scaffolding markers included — because the policy of what a caller may see (hub filtering, key stripping) belongs to the service layer, in one place, for every backend.

TTL-expired facts are skipped, not listed: an audit must show what the store will still serve, and a fact past its expiry is not it.

Defaulted to a refusal rather than required, same reasoning as Self::edge_count: an out-of-crate backend keeps compiling, and its list_memories answers with this error instead of a wrong walk.

§Errors

Returns MemoryError if the backend cannot enumerate at all, or if the walk fails.

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§

Source§

impl MemoryStore for NativeStore

Available on crate feature persistence only.