Skip to main content

rlm_rs/storage/
traits.rs

1//! Storage trait definition.
2//!
3//! Defines the interface for persistent storage backends, enabling
4//! pluggable storage implementations.
5
6use crate::core::{Buffer, Chunk, Context};
7use crate::error::Result;
8use serde::Serialize;
9
10/// Trait for persistent storage backends.
11///
12/// Implementations handle storage of RLM state including contexts,
13/// buffers, and chunks. All operations should be atomic where appropriate.
14///
15/// Note: This trait does not require `Send + Sync` as rlm-rs is a
16/// single-threaded CLI application. Implementations are not guaranteed
17/// to be thread-safe.
18pub trait Storage {
19    /// Initializes storage (creates schema, runs migrations).
20    ///
21    /// Should be idempotent - safe to call multiple times.
22    ///
23    /// # Errors
24    ///
25    /// Returns an error if schema creation or migration fails.
26    fn init(&mut self) -> Result<()>;
27
28    /// Checks if storage is initialized.
29    ///
30    /// # Errors
31    ///
32    /// Returns an error if the check cannot be performed.
33    fn is_initialized(&self) -> Result<bool>;
34
35    /// Resets all stored state.
36    ///
37    /// Deletes all data but preserves the schema.
38    ///
39    /// # Errors
40    ///
41    /// Returns an error if deletion fails.
42    fn reset(&mut self) -> Result<()>;
43
44    // ==================== Context Operations ====================
45
46    /// Saves the current context state.
47    ///
48    /// Creates or updates the context in storage.
49    ///
50    /// # Errors
51    ///
52    /// Returns an error if serialization or database write fails.
53    fn save_context(&mut self, context: &Context) -> Result<()>;
54
55    /// Loads the context state.
56    ///
57    /// Returns `None` if no context exists.
58    ///
59    /// # Errors
60    ///
61    /// Returns an error if database read or deserialization fails.
62    fn load_context(&self) -> Result<Option<Context>>;
63
64    /// Deletes the current context.
65    ///
66    /// # Errors
67    ///
68    /// Returns an error if deletion fails.
69    fn delete_context(&mut self) -> Result<()>;
70
71    // ==================== Buffer Operations ====================
72
73    /// Adds a buffer to storage.
74    ///
75    /// Returns the assigned buffer ID.
76    ///
77    /// # Errors
78    ///
79    /// Returns an error if the buffer cannot be inserted.
80    fn add_buffer(&mut self, buffer: &Buffer) -> Result<i64>;
81
82    /// Retrieves a buffer by ID.
83    ///
84    /// # Errors
85    ///
86    /// Returns an error if the query fails.
87    fn get_buffer(&self, id: i64) -> Result<Option<Buffer>>;
88
89    /// Retrieves a buffer by name.
90    ///
91    /// # Errors
92    ///
93    /// Returns an error if the query fails.
94    fn get_buffer_by_name(&self, name: &str) -> Result<Option<Buffer>>;
95
96    /// Lists all buffers.
97    ///
98    /// # Errors
99    ///
100    /// Returns an error if the query fails.
101    fn list_buffers(&self) -> Result<Vec<Buffer>>;
102
103    /// Updates an existing buffer.
104    ///
105    /// # Errors
106    ///
107    /// Returns an error if the buffer does not exist or update fails.
108    fn update_buffer(&mut self, buffer: &Buffer) -> Result<()>;
109
110    /// Deletes a buffer by ID.
111    ///
112    /// Also deletes associated chunks.
113    ///
114    /// # Errors
115    ///
116    /// Returns an error if deletion fails.
117    fn delete_buffer(&mut self, id: i64) -> Result<()>;
118
119    /// Returns the count of buffers.
120    ///
121    /// # Errors
122    ///
123    /// Returns an error if the count query fails.
124    fn buffer_count(&self) -> Result<usize>;
125
126    // ==================== Chunk Operations ====================
127
128    /// Adds chunks for a buffer.
129    ///
130    /// Should be called after buffer is created.
131    ///
132    /// # Errors
133    ///
134    /// Returns an error if chunk insertion fails.
135    fn add_chunks(&mut self, buffer_id: i64, chunks: &[Chunk]) -> Result<()>;
136
137    /// Retrieves all chunks for a buffer.
138    ///
139    /// # Errors
140    ///
141    /// Returns an error if the query fails.
142    fn get_chunks(&self, buffer_id: i64) -> Result<Vec<Chunk>>;
143
144    /// Retrieves a specific chunk by ID.
145    ///
146    /// # Errors
147    ///
148    /// Returns an error if the query fails.
149    fn get_chunk(&self, id: i64) -> Result<Option<Chunk>>;
150
151    /// Deletes all chunks for a buffer.
152    ///
153    /// # Errors
154    ///
155    /// Returns an error if deletion fails.
156    fn delete_chunks(&mut self, buffer_id: i64) -> Result<()>;
157
158    /// Returns the count of chunks for a buffer.
159    ///
160    /// # Errors
161    ///
162    /// Returns an error if the count query fails.
163    fn chunk_count(&self, buffer_id: i64) -> Result<usize>;
164
165    // ==================== Utility Operations ====================
166
167    /// Exports all buffers as a concatenated string.
168    ///
169    /// Used for the `export-buffers` command.
170    ///
171    /// # Errors
172    ///
173    /// Returns an error if buffer retrieval fails.
174    fn export_buffers(&self) -> Result<String>;
175
176    /// Gets storage statistics.
177    ///
178    /// # Errors
179    ///
180    /// Returns an error if statistics cannot be gathered.
181    fn stats(&self) -> Result<StorageStats>;
182}
183
184/// Storage statistics.
185#[derive(Debug, Clone, Default, Serialize)]
186pub struct StorageStats {
187    /// Number of buffers stored.
188    pub buffer_count: usize,
189    /// Total number of chunks across all buffers.
190    pub chunk_count: usize,
191    /// Total size of all buffer content in bytes.
192    pub total_content_size: usize,
193    /// Whether a context is stored.
194    pub has_context: bool,
195    /// Schema version.
196    pub schema_version: u32,
197    /// Database file size in bytes (if applicable).
198    pub db_size: Option<u64>,
199}
200
201/// Trait for vector-based semantic search (feature-gated).
202#[cfg(feature = "usearch-hnsw")]
203pub trait VectorStorage: Storage {
204    /// Indexes a chunk with embeddings for semantic search.
205    ///
206    /// # Errors
207    ///
208    /// Returns an error if indexing fails.
209    fn index_chunk(&mut self, chunk_id: i64, embedding: &[f32]) -> Result<()>;
210
211    /// Performs semantic search for similar chunks.
212    ///
213    /// Returns chunk IDs and similarity scores.
214    ///
215    /// # Errors
216    ///
217    /// Returns an error if the search fails.
218    fn search_similar(&self, query_embedding: &[f32], limit: usize) -> Result<Vec<(i64, f32)>>;
219
220    /// Removes vector index for a chunk.
221    ///
222    /// # Errors
223    ///
224    /// Returns an error if removal fails.
225    fn remove_index(&mut self, chunk_id: i64) -> Result<()>;
226}