Skip to main content

Storage

Struct Storage 

Source
pub struct Storage { /* private fields */ }
Expand description

SQLite-backed storage for Codemem memories, embeddings, and graph data.

Wraps rusqlite::Connection in a Mutex to satisfy Send + Sync bounds required by the StorageBackend trait.

Implementations§

Source§

impl Storage

Source

pub fn store_embedding( &self, memory_id: &str, embedding: &[f32], ) -> Result<(), CodememError>

Store an embedding for a memory.

Source

pub fn get_embedding( &self, memory_id: &str, ) -> Result<Option<Vec<f32>>, CodememError>

Get an embedding by memory ID.

Source

pub fn insert_graph_node(&self, node: &GraphNode) -> Result<(), CodememError>

Insert a graph node.

Source

pub fn get_graph_node( &self, id: &str, ) -> Result<Option<GraphNode>, CodememError>

Get a graph node by ID.

Source

pub fn delete_graph_node(&self, id: &str) -> Result<bool, CodememError>

Delete a graph node by ID.

Source

pub fn all_graph_nodes(&self) -> Result<Vec<GraphNode>, CodememError>

Get all graph nodes. Logs warnings for rows with parse errors instead of silently dropping.

Source

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

Insert a graph edge.

Source

pub fn get_edges_for_node( &self, node_id: &str, ) -> Result<Vec<Edge>, CodememError>

Get all edges from or to a node.

Source

pub fn all_graph_edges(&self) -> Result<Vec<Edge>, CodememError>

Get all graph edges.

Source

pub fn delete_graph_edges_for_node( &self, node_id: &str, ) -> Result<usize, CodememError>

Delete all graph edges connected to a node (as src or dst).

Source

pub fn graph_edges_for_namespace( &self, namespace: &str, ) -> Result<Vec<Edge>, CodememError>

Get all graph edges where both src and dst nodes belong to the given namespace.

Source§

impl Storage

Source

pub fn insert_memory(&self, memory: &MemoryNode) -> Result<(), CodememError>

Insert a new memory. Returns Err(Duplicate) if content hash already exists.

Uses BEGIN IMMEDIATE to acquire a write lock before the dedup check, ensuring the SELECT + INSERT are atomic. INSERT OR IGNORE is a safety net against the UNIQUE constraint on content_hash.

When an outer transaction is active (via begin_transaction), the method skips starting its own transaction and executes directly on the connection, so that all operations participate in the outer transaction.

Source

pub fn get_memory(&self, id: &str) -> Result<Option<MemoryNode>, CodememError>

Get a memory by ID. Updates access_count and last_accessed_at.

Source

pub fn get_memory_no_touch( &self, id: &str, ) -> Result<Option<MemoryNode>, CodememError>

Get a memory by ID without updating access_count or last_accessed_at. Use for internal/system reads (consolidation, stats, batch processing).

Source

pub fn update_memory( &self, id: &str, content: &str, importance: Option<f64>, ) -> Result<(), CodememError>

Update a memory’s content and re-hash. Returns Err(NotFound) if the ID doesn’t exist.

Source

pub fn delete_memory(&self, id: &str) -> Result<bool, CodememError>

Delete a memory by ID.

Source

pub fn delete_memory_cascade(&self, id: &str) -> Result<bool, CodememError>

Delete a memory and all related data (embeddings, graph nodes/edges) atomically. Returns true if the memory existed and was deleted.

Source

pub fn delete_memories_batch_cascade( &self, ids: &[&str], ) -> Result<usize, CodememError>

Delete multiple memories and all related data (embeddings, graph nodes/edges) atomically. Returns the number of memories that were actually deleted.

Source

pub fn list_memory_ids(&self) -> Result<Vec<String>, CodememError>

List all memory IDs with an optional limit.

Source

pub fn list_memory_ids_limited( &self, limit: Option<usize>, ) -> Result<Vec<String>, CodememError>

List memory IDs with an optional limit.

Source

pub fn list_memory_ids_for_namespace( &self, namespace: &str, ) -> Result<Vec<String>, CodememError>

List memory IDs scoped to a specific namespace.

Source

pub fn list_namespaces(&self) -> Result<Vec<String>, CodememError>

List all distinct namespaces.

Source

pub fn memory_count(&self) -> Result<usize, CodememError>

Get memory count.

Source

pub fn list_repos(&self) -> Result<Vec<Repository>, CodememError>

List all registered repositories.

Source

pub fn add_repo(&self, repo: &Repository) -> Result<(), CodememError>

Add a new repository.

Source

pub fn remove_repo(&self, id: &str) -> Result<bool, CodememError>

Remove a repository by ID.

Source

pub fn get_repo(&self, id: &str) -> Result<Option<Repository>, CodememError>

Get a repository by ID.

Source

pub fn update_repo_status( &self, id: &str, status: &str, indexed_at: Option<&str>, ) -> Result<(), CodememError>

Update a repository’s status and optionally last_indexed_at.

Source§

impl Storage

Source

pub fn integrity_check(&self) -> Result<bool, CodememError>

Run SQLite PRAGMA integrity_check. Returns true if the database is OK.

Source

pub fn schema_version(&self) -> Result<u32, CodememError>

Return the current schema version (max applied migration number).

Source

pub fn stats(&self) -> Result<StorageStats, CodememError>

Get database statistics in a single query.

Source

pub fn insert_consolidation_log( &self, cycle_type: &str, affected_count: usize, ) -> Result<(), CodememError>

Record a consolidation run.

Source

pub fn last_consolidation_runs( &self, ) -> Result<Vec<ConsolidationLogEntry>, CodememError>

Get the last consolidation run for each cycle type.

Source

pub fn get_repeated_searches( &self, min_count: usize, namespace: Option<&str>, ) -> Result<Vec<(String, usize, Vec<String>)>, CodememError>

Find repeated search patterns (Grep/Glob) by extracting the “pattern” field from memory metadata JSON. Returns (pattern, count, memory_ids) tuples where count >= min_count, ordered by count descending.

Source

pub fn get_file_hotspots( &self, min_count: usize, namespace: Option<&str>, ) -> Result<Vec<(String, usize, Vec<String>)>, CodememError>

Find file hotspots by extracting the “file_path” field from memory metadata.

Source

pub fn get_tool_usage_stats( &self, namespace: Option<&str>, ) -> Result<Vec<(String, usize)>, CodememError>

Get tool usage statistics from memory metadata. Returns (tool_name, count) pairs sorted by count descending.

Source

pub fn get_decision_chains( &self, min_count: usize, namespace: Option<&str>, ) -> Result<Vec<(String, usize, Vec<String>)>, CodememError>

Find decision chains: files with multiple Edit/Write memories over time.

Source

pub fn list_memories_by_tag( &self, tag: &str, namespace: Option<&str>, limit: usize, ) -> Result<Vec<MemoryNode>, CodememError>

List memories that contain a specific tag, optionally scoped to a namespace. Uses json_each for proper JSON array querying instead of LIKE patterns.

Source

pub fn start_session( &self, id: &str, namespace: Option<&str>, ) -> Result<(), CodememError>

Start a new session.

Source

pub fn end_session( &self, id: &str, summary: Option<&str>, ) -> Result<(), CodememError>

End a session by setting ended_at and optionally a summary.

Source

pub fn list_sessions( &self, namespace: Option<&str>, ) -> Result<Vec<Session>, CodememError>

List sessions, optionally filtered by namespace.

Source

pub fn record_session_activity( &self, session_id: &str, tool_name: &str, file_path: Option<&str>, directory: Option<&str>, pattern: Option<&str>, ) -> Result<(), CodememError>

Record a session activity event.

Source

pub fn get_session_activity_summary( &self, session_id: &str, ) -> Result<SessionActivitySummary, CodememError>

Get a summary of session activity counts using a single query with conditional aggregation.

Source

pub fn get_session_hot_directories( &self, session_id: &str, limit: usize, ) -> Result<Vec<(String, usize)>, CodememError>

Get the most active directories in a session.

Source

pub fn has_auto_insight( &self, session_id: &str, dedup_tag: &str, ) -> Result<bool, CodememError>

Check whether an auto-insight dedup tag exists for a session. Uses json_extract with proper parameter binding instead of LIKE on JSON.

Source

pub fn count_directory_reads( &self, session_id: &str, directory: &str, ) -> Result<usize, CodememError>

Count Read events in a directory during a session.

Source

pub fn was_file_read_in_session( &self, session_id: &str, file_path: &str, ) -> Result<bool, CodememError>

Check if a file was read in the current session.

Source

pub fn count_search_pattern_in_session( &self, session_id: &str, pattern: &str, ) -> Result<usize, CodememError>

Count how many times a search pattern was used in a session.

Source

pub fn find_memory_ids_by_tag( &self, tag: &str, namespace: Option<&str>, exclude_id: &str, ) -> Result<Vec<String>, CodememError>

Find memory IDs whose tags JSON array contains the given tag value. Optionally scoped to a namespace. Excludes the given exclude_id. Returns at most 50 results ordered by creation time (most recent siblings first).

Source

pub fn delete_graph_nodes_by_prefix( &self, prefix: &str, ) -> Result<usize, CodememError>

Delete all graph nodes, their edges, and their embeddings where the node ID starts with the given prefix. Returns count of nodes deleted. Wrapped in a transaction so all three DELETEs are atomic.

Source§

impl Storage

Source

pub fn open(path: &Path) -> Result<Self, CodememError>

Open (or create) a Codemem database at the given path.

Source

pub fn open_with_config( path: &Path, cache_size_mb: Option<u32>, busy_timeout_secs: Option<u64>, ) -> Result<Self, CodememError>

Open a database with explicit storage configuration overrides.

Source

pub fn open_without_migrations(path: &Path) -> Result<Self, CodememError>

Open an existing database without running migrations.

Use this in lifecycle hooks (context, prompt, summarize) where the database has already been migrated by codemem init or codemem serve, to avoid SQLITE_BUSY race conditions with the concurrent MCP server.

Source

pub fn open_without_migrations_with_config( path: &Path, cache_size_mb: Option<u32>, busy_timeout_secs: Option<u64>, ) -> Result<Self, CodememError>

Open without migrations, with explicit storage configuration overrides.

Source

pub fn open_in_memory() -> Result<Self, CodememError>

Open an in-memory database (for testing).

Source

pub fn content_hash(content: &str) -> String

Compute SHA-256 hash of content for deduplication.

Trait Implementations§

Source§

impl StorageBackend for Storage

Source§

fn delete_memory_cascade(&self, id: &str) -> Result<bool, CodememError>

M1: Override with transactional cascade delete.

Source§

fn delete_memories_batch_cascade( &self, ids: &[&str], ) -> Result<usize, CodememError>

Override with transactional batch cascade delete.

Source§

fn insert_memory(&self, memory: &MemoryNode) -> Result<(), CodememError>

Insert a new memory. Returns Err(Duplicate) if content hash already exists.
Source§

fn get_memory(&self, id: &str) -> Result<Option<MemoryNode>, CodememError>

Get a memory by ID. Updates access_count and last_accessed_at.
Source§

fn get_memory_no_touch( &self, id: &str, ) -> Result<Option<MemoryNode>, CodememError>

Get a memory by ID without updating access_count or last_accessed_at. Use this for internal/system reads (consolidation checks, stats, batch processing).
Source§

fn update_memory( &self, id: &str, content: &str, importance: Option<f64>, ) -> Result<(), CodememError>

Update a memory’s content and optionally its importance. Re-computes content hash.
Source§

fn delete_memory(&self, id: &str) -> Result<bool, CodememError>

Delete a memory by ID. Returns true if a row was deleted.
Source§

fn list_memory_ids(&self) -> Result<Vec<String>, CodememError>

List all memory IDs, ordered by created_at descending.
Source§

fn list_memory_ids_for_namespace( &self, namespace: &str, ) -> Result<Vec<String>, CodememError>

List memory IDs scoped to a specific namespace.
Source§

fn find_memory_ids_by_tag( &self, tag: &str, namespace: Option<&str>, exclude_id: &str, ) -> Result<Vec<String>, CodememError>

Find memory IDs whose tags contain the given tag value. Optionally scoped to a namespace. Excludes exclude_id.
Source§

fn list_namespaces(&self) -> Result<Vec<String>, CodememError>

List all distinct namespaces.
Source§

fn memory_count(&self) -> Result<usize, CodememError>

Get total memory count.
Source§

fn get_memories_batch( &self, ids: &[&str], ) -> Result<Vec<MemoryNode>, CodememError>

Get multiple memories by IDs in a single batch operation.
Source§

fn store_embedding( &self, memory_id: &str, embedding: &[f32], ) -> Result<(), CodememError>

Store an embedding vector for a memory.
Source§

fn get_embedding( &self, memory_id: &str, ) -> Result<Option<Vec<f32>>, CodememError>

Get an embedding by memory ID.
Source§

fn delete_embedding(&self, memory_id: &str) -> Result<bool, CodememError>

Delete an embedding by memory ID. Returns true if a row was deleted.
Source§

fn list_all_embeddings(&self) -> Result<Vec<(String, Vec<f32>)>, CodememError>

List all stored embeddings as (memory_id, embedding_vector) pairs.
Source§

fn insert_graph_node(&self, node: &GraphNode) -> Result<(), CodememError>

Insert or replace a graph node.
Source§

fn get_graph_node(&self, id: &str) -> Result<Option<GraphNode>, CodememError>

Get a graph node by ID.
Source§

fn delete_graph_node(&self, id: &str) -> Result<bool, CodememError>

Delete a graph node by ID. Returns true if a row was deleted.
Source§

fn all_graph_nodes(&self) -> Result<Vec<GraphNode>, CodememError>

Get all graph nodes.
Source§

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

Insert or replace a graph edge.
Source§

fn get_edges_for_node(&self, node_id: &str) -> Result<Vec<Edge>, CodememError>

Get all edges from or to a node.
Source§

fn all_graph_edges(&self) -> Result<Vec<Edge>, CodememError>

Get all graph edges.
Source§

fn delete_graph_edges_for_node( &self, node_id: &str, ) -> Result<usize, CodememError>

Delete all graph edges connected to a node. Returns count deleted.
Source§

fn delete_graph_nodes_by_prefix( &self, prefix: &str, ) -> Result<usize, CodememError>

Delete all graph nodes, edges, and embeddings whose node ID starts with the given prefix. Returns count of nodes deleted.
Source§

fn start_session( &self, id: &str, namespace: Option<&str>, ) -> Result<(), CodememError>

Start a new session.
Source§

fn end_session( &self, id: &str, summary: Option<&str>, ) -> Result<(), CodememError>

End a session with optional summary.
Source§

fn list_sessions( &self, namespace: Option<&str>, limit: usize, ) -> Result<Vec<Session>, CodememError>

List sessions, optionally filtered by namespace, up to limit.
Source§

fn insert_consolidation_log( &self, cycle_type: &str, affected_count: usize, ) -> Result<(), CodememError>

Record a consolidation run.
Source§

fn last_consolidation_runs( &self, ) -> Result<Vec<ConsolidationLogEntry>, CodememError>

Get the last consolidation run for each cycle type.
Source§

fn get_repeated_searches( &self, min_count: usize, namespace: Option<&str>, ) -> Result<Vec<(String, usize, Vec<String>)>, CodememError>

Find repeated search patterns. Returns (pattern, count, memory_ids).
Source§

fn get_file_hotspots( &self, min_count: usize, namespace: Option<&str>, ) -> Result<Vec<(String, usize, Vec<String>)>, CodememError>

Find file hotspots. Returns (file_path, count, memory_ids).
Source§

fn get_tool_usage_stats( &self, namespace: Option<&str>, ) -> Result<Vec<(String, usize)>, CodememError>

Get tool usage statistics. Returns (tool_name, count) pairs.
Source§

fn get_decision_chains( &self, min_count: usize, namespace: Option<&str>, ) -> Result<Vec<(String, usize, Vec<String>)>, CodememError>

Find decision chains. Returns (file_path, count, memory_ids).
Source§

fn decay_stale_memories( &self, threshold_ts: i64, decay_factor: f64, ) -> Result<usize, CodememError>

Decay importance of stale memories older than threshold_ts by decay_factor. Returns count of affected memories.
Source§

fn list_memories_for_creative( &self, ) -> Result<Vec<(String, String, Vec<String>)>, CodememError>

List memories for creative consolidation: (id, memory_type, tags).
Source§

fn find_hash_duplicates( &self, ) -> Result<Vec<(String, String, f64)>, CodememError>

Find near-duplicate memories by content hash prefix matching. Returns (id1, id2, similarity) pairs. Only catches exact content matches (hash prefix), not semantic near-duplicates.
Source§

fn find_forgettable( &self, importance_threshold: f64, ) -> Result<Vec<String>, CodememError>

Find memories eligible for forgetting (low importance). Returns list of memory IDs.
Source§

fn insert_memories_batch( &self, memories: &[MemoryNode], ) -> Result<(), CodememError>

Insert multiple memories in a single batch. Default impl calls insert_memory in a loop.
Source§

fn store_embeddings_batch( &self, items: &[(&str, &[f32])], ) -> Result<(), CodememError>

Store multiple embeddings in a single batch. Default impl calls store_embedding in a loop.
Source§

fn load_file_hashes(&self) -> Result<HashMap<String, String>, CodememError>

Load all file hashes for incremental indexing. Returns path -> hash map.
Source§

fn save_file_hashes( &self, hashes: &HashMap<String, String>, ) -> Result<(), CodememError>

Save file hashes for incremental indexing.
Source§

fn insert_graph_nodes_batch( &self, nodes: &[GraphNode], ) -> Result<(), CodememError>

Insert multiple graph nodes in a single batch. Default impl calls insert_graph_node in a loop.
Source§

fn insert_graph_edges_batch(&self, edges: &[Edge]) -> Result<(), CodememError>

Insert multiple graph edges in a single batch. Default impl calls insert_graph_edge in a loop.
Source§

fn get_stale_memories_for_decay( &self, threshold_ts: i64, ) -> Result<Vec<(String, f64, u32, i64)>, CodememError>

Fetch stale memories with access metadata for power-law decay. Returns (id, importance, access_count, last_accessed_at).
Source§

fn batch_update_importance( &self, updates: &[(String, f64)], ) -> Result<usize, CodememError>

Batch-update importance values. Returns count of updated rows.
Source§

fn session_count(&self, namespace: Option<&str>) -> Result<usize, CodememError>

Total session count, optionally filtered by namespace.
Source§

fn find_unembedded_memories( &self, ) -> Result<Vec<(String, String)>, CodememError>

Find memories that have no embeddings yet. Returns (id, content) pairs.
Source§

fn search_graph_nodes( &self, query: &str, namespace: Option<&str>, limit: usize, ) -> Result<Vec<GraphNode>, CodememError>

Search graph nodes by label (case-insensitive LIKE). Returns matching nodes sorted by centrality descending, limited to limit results.
Source§

fn list_memories_by_tag( &self, tag: &str, namespace: Option<&str>, limit: usize, ) -> Result<Vec<MemoryNode>, CodememError>

List memories matching a specific tag, with optional namespace filter.
Source§

fn list_memories_filtered( &self, namespace: Option<&str>, memory_type: Option<&str>, ) -> Result<Vec<MemoryNode>, CodememError>

List memories with optional namespace and memory_type filters.
Source§

fn record_session_activity( &self, session_id: &str, tool_name: &str, file_path: Option<&str>, directory: Option<&str>, pattern: Option<&str>, ) -> Result<(), CodememError>

Record a session activity event (tool use with context).
Source§

fn get_session_activity_summary( &self, session_id: &str, ) -> Result<SessionActivitySummary, CodememError>

Get a summary of session activity counts.
Source§

fn get_session_hot_directories( &self, session_id: &str, limit: usize, ) -> Result<Vec<(String, usize)>, CodememError>

Get the most active directories in a session. Returns (directory, count) pairs.
Source§

fn has_auto_insight( &self, session_id: &str, dedup_tag: &str, ) -> Result<bool, CodememError>

Check whether a particular auto-insight dedup tag already exists for a session.
Source§

fn count_directory_reads( &self, session_id: &str, directory: &str, ) -> Result<usize, CodememError>

Count how many Read events occurred in a directory during a session.
Source§

fn was_file_read_in_session( &self, session_id: &str, file_path: &str, ) -> Result<bool, CodememError>

Check if a file was read in the current session.
Source§

fn count_search_pattern_in_session( &self, session_id: &str, pattern: &str, ) -> Result<usize, CodememError>

Count how many times a search pattern was used in a session.
Source§

fn stats(&self) -> Result<StorageStats, CodememError>

Get database statistics.
Source§

fn begin_transaction(&self) -> Result<(), CodememError>

Begin an explicit transaction. Read more
Source§

fn commit_transaction(&self) -> Result<(), CodememError>

Commit the active transaction started by begin_transaction. Read more
Source§

fn rollback_transaction(&self) -> Result<(), CodememError>

Roll back the active transaction started by begin_transaction. Read more
Source§

fn list_repos(&self) -> Result<Vec<Repository>, CodememError>

List all registered repositories.
Source§

fn add_repo(&self, repo: &Repository) -> Result<(), CodememError>

Add a new repository.
Source§

fn get_repo(&self, id: &str) -> Result<Option<Repository>, CodememError>

Get a repository by ID.
Source§

fn remove_repo(&self, id: &str) -> Result<bool, CodememError>

Remove a repository by ID. Returns true if it existed.
Source§

fn update_repo_status( &self, id: &str, status: &str, indexed_at: Option<&str>, ) -> Result<(), CodememError>

Update a repository’s status and optionally its last-indexed timestamp.

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> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
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> Same for T

Source§

type Output = T

Should always be Self
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.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more