use crate::error::EngramError;
pub use crate::types::StorageStats;
use crate::types::{
CreateMemoryInput, CrossReference, EdgeType, ListOptions, Memory, MemoryId, SearchOptions,
SearchResult, UpdateMemoryInput,
};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BatchCreateResult {
pub created: Vec<Memory>,
pub failed: Vec<(usize, String)>,
pub elapsed_ms: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BatchDeleteResult {
pub deleted_count: usize,
pub not_found: Vec<MemoryId>,
pub failed: Vec<(MemoryId, String)>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SyncResult {
pub success: bool,
pub pushed_count: usize,
pub pulled_count: usize,
pub conflicts_resolved: usize,
pub error: Option<String>,
pub new_version: i64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SyncDelta {
pub created: Vec<Memory>,
pub updated: Vec<Memory>,
pub deleted: Vec<MemoryId>,
pub version: u64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SyncState {
pub local_version: u64,
pub remote_version: Option<u64>,
pub last_sync: Option<chrono::DateTime<chrono::Utc>>,
pub has_pending_changes: bool,
pub pending_count: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HealthStatus {
pub healthy: bool,
pub latency_ms: f64,
pub error: Option<String>,
pub details: HashMap<String, String>,
}
pub trait StorageBackend: Send + Sync {
fn create_memory(&self, input: CreateMemoryInput) -> Result<Memory, EngramError>;
fn get_memory(&self, id: MemoryId) -> Result<Option<Memory>, EngramError>;
fn update_memory(&self, id: MemoryId, input: UpdateMemoryInput) -> Result<Memory, EngramError>;
fn delete_memory(&self, id: MemoryId) -> Result<(), EngramError>;
fn create_memories_batch(
&self,
inputs: Vec<CreateMemoryInput>,
) -> Result<BatchCreateResult, EngramError>;
fn delete_memories_batch(&self, ids: Vec<MemoryId>) -> Result<BatchDeleteResult, EngramError>;
fn list_memories(&self, options: ListOptions) -> Result<Vec<Memory>, EngramError>;
fn count_memories(&self, options: ListOptions) -> Result<i64, EngramError>;
fn search_memories(
&self,
query: &str,
options: SearchOptions,
) -> Result<Vec<SearchResult>, EngramError>;
fn create_crossref(
&self,
from_id: MemoryId,
to_id: MemoryId,
edge_type: EdgeType,
score: f32,
) -> Result<CrossReference, EngramError>;
fn get_crossrefs(&self, memory_id: MemoryId) -> Result<Vec<CrossReference>, EngramError>;
fn delete_crossref(&self, from_id: MemoryId, to_id: MemoryId) -> Result<(), EngramError>;
fn list_tags(&self) -> Result<Vec<(String, i64)>, EngramError>;
fn get_memories_by_tag(
&self,
tag: &str,
limit: Option<usize>,
) -> Result<Vec<Memory>, EngramError>;
fn list_workspaces(&self) -> Result<Vec<(String, i64)>, EngramError>;
fn get_workspace_stats(&self, workspace: &str) -> Result<HashMap<String, i64>, EngramError>;
fn move_to_workspace(&self, ids: Vec<MemoryId>, workspace: &str) -> Result<usize, EngramError>;
fn get_stats(&self) -> Result<StorageStats, EngramError>;
fn health_check(&self) -> Result<HealthStatus, EngramError>;
fn optimize(&self) -> Result<(), EngramError>;
fn backend_name(&self) -> &'static str;
fn schema_version(&self) -> Result<i32, EngramError>;
}
pub trait TransactionalBackend: StorageBackend {
fn with_transaction<F, T>(&self, f: F) -> Result<T, EngramError>
where
F: FnOnce(&dyn StorageBackend) -> Result<T, EngramError>;
fn savepoint(&self, name: &str) -> Result<(), EngramError>;
fn release_savepoint(&self, name: &str) -> Result<(), EngramError>;
fn rollback_to_savepoint(&self, name: &str) -> Result<(), EngramError>;
}
pub trait CloudSyncBackend: StorageBackend {
fn pull(&self) -> Result<SyncResult, EngramError>;
fn push(&self) -> Result<SyncResult, EngramError>;
fn sync_delta(&self, since_version: u64) -> Result<SyncDelta, EngramError>;
fn sync_state(&self) -> Result<SyncState, EngramError>;
fn force_sync(&self) -> Result<SyncResult, EngramError>;
}