use async_trait::async_trait;
use crate::sync_item::SyncItem;
use crate::search::SqlParam;
use thiserror::Error;
#[derive(Error, Debug)]
pub enum StorageError {
#[error("Item not found")]
NotFound,
#[error("Storage backend error: {0}")]
Backend(String),
#[error("Connection error: {0}")]
Connection(String),
#[error("Data corruption detected for '{id}': expected hash {expected}, got {actual}")]
Corruption {
id: String,
expected: String,
actual: String,
},
}
#[derive(Debug)]
pub struct BatchWriteResult {
pub batch_id: String,
pub written: usize,
pub verified: bool,
}
#[async_trait]
pub trait CacheStore: Send + Sync {
async fn get(&self, id: &str) -> Result<Option<SyncItem>, StorageError>;
async fn put(&self, item: &SyncItem) -> Result<(), StorageError>;
async fn delete(&self, id: &str) -> Result<(), StorageError>;
async fn exists(&self, id: &str) -> Result<bool, StorageError>;
async fn put_batch(&self, items: &[SyncItem]) -> Result<BatchWriteResult, StorageError> {
self.put_batch_with_ttl(items, None).await
}
async fn put_batch_with_ttl(&self, items: &[SyncItem], ttl_secs: Option<u64>) -> Result<BatchWriteResult, StorageError> {
let _ = ttl_secs;
for item in items {
self.put(item).await?;
}
Ok(BatchWriteResult {
batch_id: String::new(),
written: items.len(),
verified: true,
})
}
async fn ft_create(&self, args: &[String]) -> Result<(), StorageError> {
let _ = args;
Err(StorageError::Backend("FT.CREATE not supported".into()))
}
async fn ft_dropindex(&self, index: &str) -> Result<(), StorageError> {
let _ = index;
Err(StorageError::Backend("FT.DROPINDEX not supported".into()))
}
async fn ft_search(&self, index: &str, query: &str, limit: usize) -> Result<Vec<String>, StorageError> {
let _ = (index, query, limit);
Err(StorageError::Backend("FT.SEARCH not supported".into()))
}
async fn ft_search_with_params(
&self,
index: &str,
query: &str,
params: &[(String, Vec<u8>)],
limit: usize,
) -> Result<Vec<String>, StorageError> {
let _ = (index, query, params, limit);
Err(StorageError::Backend("FT.SEARCH with PARAMS not supported".into()))
}
}
#[async_trait]
pub trait ArchiveStore: Send + Sync {
async fn get(&self, id: &str) -> Result<Option<SyncItem>, StorageError>;
async fn put(&self, item: &SyncItem) -> Result<(), StorageError>;
async fn delete(&self, id: &str) -> Result<(), StorageError>;
async fn exists(&self, id: &str) -> Result<bool, StorageError>;
async fn put_batch(&self, items: &mut [SyncItem]) -> Result<BatchWriteResult, StorageError> {
for item in items.iter() {
self.put(item).await?;
}
Ok(BatchWriteResult {
batch_id: String::new(),
written: items.len(),
verified: true,
})
}
async fn scan_keys(&self, offset: u64, limit: usize) -> Result<Vec<String>, StorageError>;
async fn count_all(&self) -> Result<u64, StorageError>;
async fn search(&self, where_clause: &str, params: &[SqlParam], limit: usize) -> Result<Vec<SyncItem>, StorageError> {
let _ = (where_clause, params, limit);
Err(StorageError::Backend("SQL search not supported".into()))
}
async fn count_where(&self, where_clause: &str, params: &[SqlParam]) -> Result<u64, StorageError> {
let _ = (where_clause, params);
Err(StorageError::Backend("SQL count not supported".into()))
}
}