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#[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#[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#[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#[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#[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#[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
65pub trait StorageBackend: Send + Sync {
70 fn create_memory(&self, input: CreateMemoryInput) -> Result<Memory, EngramError>;
74
75 fn get_memory(&self, id: MemoryId) -> Result<Option<Memory>, EngramError>;
77
78 fn update_memory(&self, id: MemoryId, input: UpdateMemoryInput) -> Result<Memory, EngramError>;
80
81 fn delete_memory(&self, id: MemoryId) -> Result<(), EngramError>;
83
84 fn create_memories_batch(
88 &self,
89 inputs: Vec<CreateMemoryInput>,
90 ) -> Result<BatchCreateResult, EngramError>;
91
92 fn delete_memories_batch(&self, ids: Vec<MemoryId>) -> Result<BatchDeleteResult, EngramError>;
94
95 fn list_memories(&self, options: ListOptions) -> Result<Vec<Memory>, EngramError>;
99
100 fn count_memories(&self, options: ListOptions) -> Result<i64, EngramError>;
102
103 fn search_memories(
105 &self,
106 query: &str,
107 options: SearchOptions,
108 ) -> Result<Vec<SearchResult>, EngramError>;
109
110 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 fn get_crossrefs(&self, memory_id: MemoryId) -> Result<Vec<CrossReference>, EngramError>;
123
124 fn delete_crossref(&self, from_id: MemoryId, to_id: MemoryId) -> Result<(), EngramError>;
126
127 fn list_tags(&self) -> Result<Vec<(String, i64)>, EngramError>;
131
132 fn get_memories_by_tag(
134 &self,
135 tag: &str,
136 limit: Option<usize>,
137 ) -> Result<Vec<Memory>, EngramError>;
138
139 fn list_workspaces(&self) -> Result<Vec<(String, i64)>, EngramError>;
143
144 fn get_workspace_stats(&self, workspace: &str) -> Result<HashMap<String, i64>, EngramError>;
146
147 fn move_to_workspace(&self, ids: Vec<MemoryId>, workspace: &str) -> Result<usize, EngramError>;
149
150 fn get_stats(&self) -> Result<StorageStats, EngramError>;
154
155 fn health_check(&self) -> Result<HealthStatus, EngramError>;
157
158 fn optimize(&self) -> Result<(), EngramError>;
160
161 fn backend_name(&self) -> &'static str;
163
164 fn schema_version(&self) -> Result<i32, EngramError>;
166}
167
168pub trait TransactionalBackend: StorageBackend {
170 fn with_transaction<F, T>(&self, f: F) -> Result<T, EngramError>
172 where
173 F: FnOnce(&dyn StorageBackend) -> Result<T, EngramError>;
174
175 fn savepoint(&self, name: &str) -> Result<(), EngramError>;
177
178 fn release_savepoint(&self, name: &str) -> Result<(), EngramError>;
180
181 fn rollback_to_savepoint(&self, name: &str) -> Result<(), EngramError>;
183}
184
185pub trait CloudSyncBackend: StorageBackend {
187 fn pull(&self) -> Result<SyncResult, EngramError>;
189
190 fn push(&self) -> Result<SyncResult, EngramError>;
192
193 fn sync_delta(&self, since_version: u64) -> Result<SyncDelta, EngramError>;
195
196 fn sync_state(&self) -> Result<SyncState, EngramError>;
198
199 fn force_sync(&self) -> Result<SyncResult, EngramError>;
201}