Skip to main content

engram/storage/
backend.rs

1use crate::error::EngramError;
2pub use crate::types::StorageStats;
3use crate::types::{
4    CreateMemoryInput, CrossReference, EdgeType, ListOptions, Memory, MemoryId, SearchOptions,
5    SearchResult, UpdateMemoryInput,
6};
7use serde::{Deserialize, Serialize};
8use std::collections::HashMap;
9
10/// Result of a batch creation operation
11#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct BatchCreateResult {
13    pub created: Vec<Memory>,
14    pub failed: Vec<(usize, String)>,
15    pub elapsed_ms: f64,
16}
17
18/// Result of a batch deletion operation
19#[derive(Debug, Clone, Serialize, Deserialize)]
20pub struct BatchDeleteResult {
21    pub deleted_count: usize,
22    pub not_found: Vec<MemoryId>,
23    pub failed: Vec<(MemoryId, String)>,
24}
25
26/// Result of a sync operation
27#[derive(Debug, Clone, Serialize, Deserialize)]
28pub struct SyncResult {
29    pub success: bool,
30    pub pushed_count: usize,
31    pub pulled_count: usize,
32    pub conflicts_resolved: usize,
33    pub error: Option<String>,
34    pub new_version: i64,
35}
36
37/// Delta of changes for synchronization
38#[derive(Debug, Clone, Serialize, Deserialize)]
39pub struct SyncDelta {
40    pub created: Vec<Memory>,
41    pub updated: Vec<Memory>,
42    pub deleted: Vec<MemoryId>,
43    pub version: u64,
44}
45
46/// Current state of synchronization
47#[derive(Debug, Clone, Serialize, Deserialize)]
48pub struct SyncState {
49    pub local_version: u64,
50    pub remote_version: Option<u64>,
51    pub last_sync: Option<chrono::DateTime<chrono::Utc>>,
52    pub has_pending_changes: bool,
53    pub pending_count: usize,
54}
55
56/// Health status of the storage backend
57#[derive(Debug, Clone, Serialize, Deserialize)]
58pub struct HealthStatus {
59    pub healthy: bool,
60    pub latency_ms: f64,
61    pub error: Option<String>,
62    pub details: HashMap<String, String>,
63}
64
65/// Core storage backend trait for Engram (ENG-14)
66///
67/// This trait defines the interface for all storage operations, allowing
68/// for multiple backend implementations (SQLite, Turso, Meilisearch).
69pub trait StorageBackend: Send + Sync {
70    // --- Memory CRUD ---
71
72    /// Create a new memory
73    fn create_memory(&self, input: CreateMemoryInput) -> Result<Memory, EngramError>;
74
75    /// Get a memory by ID
76    fn get_memory(&self, id: MemoryId) -> Result<Option<Memory>, EngramError>;
77
78    /// Update a memory
79    fn update_memory(&self, id: MemoryId, input: UpdateMemoryInput) -> Result<Memory, EngramError>;
80
81    /// Delete a memory (soft delete)
82    fn delete_memory(&self, id: MemoryId) -> Result<(), EngramError>;
83
84    // --- Batch Operations ---
85
86    /// Create multiple memories in a single transaction
87    fn create_memories_batch(
88        &self,
89        inputs: Vec<CreateMemoryInput>,
90    ) -> Result<BatchCreateResult, EngramError>;
91
92    /// Delete multiple memories in a single transaction
93    fn delete_memories_batch(&self, ids: Vec<MemoryId>) -> Result<BatchDeleteResult, EngramError>;
94
95    // --- Query Operations ---
96
97    /// List memories with filters
98    fn list_memories(&self, options: ListOptions) -> Result<Vec<Memory>, EngramError>;
99
100    /// Count memories matching filters
101    fn count_memories(&self, options: ListOptions) -> Result<i64, EngramError>;
102
103    /// Search memories using hybrid search
104    fn search_memories(
105        &self,
106        query: &str,
107        options: SearchOptions,
108    ) -> Result<Vec<SearchResult>, EngramError>;
109
110    // --- Graph Operations ---
111
112    /// Create a cross-reference between memories
113    fn create_crossref(
114        &self,
115        from_id: MemoryId,
116        to_id: MemoryId,
117        edge_type: EdgeType,
118        score: f32,
119    ) -> Result<CrossReference, EngramError>;
120
121    /// Get cross-references for a memory
122    fn get_crossrefs(&self, memory_id: MemoryId) -> Result<Vec<CrossReference>, EngramError>;
123
124    /// Delete a cross-reference
125    fn delete_crossref(&self, from_id: MemoryId, to_id: MemoryId) -> Result<(), EngramError>;
126
127    // --- Tag Operations ---
128
129    /// List all tags with usage counts
130    fn list_tags(&self) -> Result<Vec<(String, i64)>, EngramError>;
131
132    /// Get memories with a specific tag
133    fn get_memories_by_tag(
134        &self,
135        tag: &str,
136        limit: Option<usize>,
137    ) -> Result<Vec<Memory>, EngramError>;
138
139    // --- Workspace Operations ---
140
141    /// List all workspaces with memory counts
142    fn list_workspaces(&self) -> Result<Vec<(String, i64)>, EngramError>;
143
144    /// Get detailed statistics for a workspace
145    fn get_workspace_stats(&self, workspace: &str) -> Result<HashMap<String, i64>, EngramError>;
146
147    /// Move memories to a different workspace
148    fn move_to_workspace(&self, ids: Vec<MemoryId>, workspace: &str) -> Result<usize, EngramError>;
149
150    // --- Maintenance & Metadata ---
151
152    /// Get storage statistics
153    fn get_stats(&self) -> Result<StorageStats, EngramError>;
154
155    /// Check storage health
156    fn health_check(&self) -> Result<HealthStatus, EngramError>;
157
158    /// Run optimization (e.g., VACUUM)
159    fn optimize(&self) -> Result<(), EngramError>;
160
161    /// Get backend name identifier
162    fn backend_name(&self) -> &'static str;
163
164    /// Get current schema version
165    fn schema_version(&self) -> Result<i32, EngramError>;
166}
167
168/// Extension trait for backends that support transactions (ENG-18)
169pub trait TransactionalBackend: StorageBackend {
170    /// Execute a closure within a transaction
171    fn with_transaction<F, T>(&self, f: F) -> Result<T, EngramError>
172    where
173        F: FnOnce(&dyn StorageBackend) -> Result<T, EngramError>;
174
175    /// create a savepoint
176    fn savepoint(&self, name: &str) -> Result<(), EngramError>;
177
178    /// release a savepoint
179    fn release_savepoint(&self, name: &str) -> Result<(), EngramError>;
180
181    /// rollback to a savepoint
182    fn rollback_to_savepoint(&self, name: &str) -> Result<(), EngramError>;
183}
184
185/// Extension trait for backends that support cloud synchronization (ENG-16)
186pub trait CloudSyncBackend: StorageBackend {
187    /// Pull changes from cloud
188    fn pull(&self) -> Result<SyncResult, EngramError>;
189
190    /// Push changes to cloud
191    fn push(&self) -> Result<SyncResult, EngramError>;
192
193    /// Get delta changes since version
194    fn sync_delta(&self, since_version: u64) -> Result<SyncDelta, EngramError>;
195
196    /// Get current sync state
197    fn sync_state(&self) -> Result<SyncState, EngramError>;
198
199    /// Force a full sync (push then pull)
200    fn force_sync(&self) -> Result<SyncResult, EngramError>;
201}