use async_trait::async_trait;
use chrono::{DateTime, Utc};
use serde::{de::DeserializeOwned, Serialize};
use std::fmt::Debug;
use super::error::{StorageError, StorageResult};
use super::types::{
Batch, EntryMetadata, Operation, Query, StorageBackend, StorageEntry, StorageHealth,
StorageMetadata, StorageStats, Transaction,
};
#[async_trait]
pub trait Storage: Send + Sync + Debug {
fn backend(&self) -> StorageBackend;
async fn metadata(&self) -> StorageResult<StorageMetadata>;
async fn health_check(&self) -> StorageResult<StorageHealth>;
async fn stats(&self) -> StorageResult<StorageStats>;
async fn insert<T: Serialize + DeserializeOwned + Send + Sync>(
&self,
table: &str,
key: &str,
value: &T,
) -> StorageResult<()>
where
Self: Sized;
async fn insert_with_ttl<T: Serialize + Send + Sync>(
&self,
table: &str,
key: &str,
value: &T,
ttl_seconds: i64,
) -> StorageResult<()>
where
Self: Sized;
async fn get<T: DeserializeOwned + Serialize + Send + Sync>(
&self,
table: &str,
key: &str,
) -> StorageResult<Option<StorageEntry<T>>>
where
Self: Sized;
async fn update<T: Serialize + Send + Sync>(
&self,
table: &str,
key: &str,
value: &T,
) -> StorageResult<()>
where
Self: Sized;
async fn update_versioned<T: Serialize + Send + Sync>(
&self,
table: &str,
key: &str,
value: &T,
expected_version: u64,
) -> StorageResult<()>
where
Self: Sized;
async fn delete(&self, table: &str, key: &str) -> StorageResult<()>;
async fn exists(&self, table: &str, key: &str) -> StorageResult<bool>;
async fn execute_batch(&self, batch: Batch) -> StorageResult<()>;
async fn query<T: DeserializeOwned + Serialize + Send + Sync + 'static>(
&self,
query: Query,
) -> StorageResult<Vec<StorageEntry<T>>>
where
Self: Sized;
async fn count(&self, query: Query) -> StorageResult<usize>;
async fn begin_transaction(&self) -> StorageResult<Transaction>;
async fn commit_transaction(&self, transaction: Transaction) -> StorageResult<()>;
async fn rollback_transaction(&self, transaction: Transaction) -> StorageResult<()>;
async fn scan_prefix(&self, table: &str, prefix: &str) -> StorageResult<Vec<String>>;
async fn get_multi<T: DeserializeOwned + Serialize + Send + Sync>(
&self,
table: &str,
keys: Vec<String>,
) -> StorageResult<Vec<Option<StorageEntry<T>>>>
where
Self: Sized;
async fn delete_multi(&self, table: &str, keys: Vec<String>) -> StorageResult<()>;
async fn compare_and_swap<T: Serialize + Send + Sync>(
&self,
table: &str,
key: &str,
expected_version: u64,
new_value: &T,
) -> StorageResult<bool>
where
Self: Sized;
async fn get_modified_since<T: DeserializeOwned + Serialize + Send + Sync + 'static>(
&self,
table: &str,
since: DateTime<Utc>,
) -> StorageResult<Vec<StorageEntry<T>>>
where
Self: Sized;
async fn get_expiring_before<T: DeserializeOwned + Serialize + Send + Sync + 'static>(
&self,
table: &str,
before: DateTime<Utc>,
) -> StorageResult<Vec<StorageEntry<T>>>
where
Self: Sized;
async fn cleanup_expired(&self, table: &str) -> StorageResult<usize>;
async fn compact(&self) -> StorageResult<()>;
async fn flush(&self) -> StorageResult<()>;
async fn initialize(&mut self) -> StorageResult<()>;
async fn shutdown(&mut self) -> StorageResult<()>;
}
#[async_trait]
pub trait CacheStorage: Storage {
async fn ttl(&self, table: &str, key: &str) -> StorageResult<Option<i64>>;
async fn expire(&self, table: &str, key: &str, ttl_seconds: i64) -> StorageResult<()>;
async fn persist(&self, table: &str, key: &str) -> StorageResult<()>;
async fn increment(&self, table: &str, key: &str, delta: i64) -> StorageResult<i64>;
async fn decrement(&self, table: &str, key: &str, delta: i64) -> StorageResult<i64>;
async fn cache_stats(&self) -> StorageResult<CacheStats>;
}
#[derive(Debug, Clone)]
pub struct CacheStats {
pub hits: u64,
pub misses: u64,
pub evictions: u64,
pub memory_used_bytes: u64,
pub memory_available_bytes: u64,
pub keys_count: usize,
}
impl CacheStats {
pub fn hit_rate(&self) -> f64 {
let total = self.hits + self.misses;
if total == 0 {
0.0
} else {
self.hits as f64 / total as f64
}
}
}
#[async_trait]
pub trait RelationalStorage: Storage {
async fn execute_sql(&self, sql: &str, params: Vec<SqlParam>) -> StorageResult<SqlResult>;
async fn query_sql<T: DeserializeOwned + Send + Sync>(
&self,
sql: &str,
params: Vec<SqlParam>,
) -> StorageResult<Vec<T>>
where
Self: Sized;
async fn create_index(
&self,
table: &str,
index_name: &str,
columns: Vec<String>,
unique: bool,
) -> StorageResult<()>;
async fn drop_index(&self, index_name: &str) -> StorageResult<()>;
async fn vacuum(&self, table: &str) -> StorageResult<()>;
async fn analyze(&self, table: &str) -> StorageResult<()>;
}
#[derive(Debug, Clone)]
pub enum SqlParam {
String(String),
Integer(i64),
Float(f64),
Boolean(bool),
DateTime(DateTime<Utc>),
Null,
}
#[derive(Debug, Clone)]
pub struct SqlResult {
pub rows_affected: u64,
}
#[async_trait]
pub trait KeyValueStorage: Storage {
async fn get_bytes(&self, table: &str, key: &str) -> StorageResult<Option<Vec<u8>>>;
async fn set_bytes(&self, table: &str, key: &str, value: Vec<u8>) -> StorageResult<()>;
async fn iter_prefix(&self, table: &str, prefix: &str) -> StorageResult<Vec<(String, Vec<u8>)>>;
async fn get_range(
&self,
table: &str,
start: &str,
end: &str,
) -> StorageResult<Vec<(String, Vec<u8>)>>;
async fn merge(&self, table: &str, key: &str, value: Vec<u8>) -> StorageResult<()>;
}
#[async_trait]
pub trait PubSubStorage: Storage {
async fn publish(&self, channel: &str, message: &[u8]) -> StorageResult<usize>;
async fn subscribe(&self, channel: &str) -> StorageResult<Box<dyn Subscriber>>;
async fn unsubscribe(&self, channel: &str) -> StorageResult<()>;
}
#[async_trait]
pub trait Subscriber: Send + Sync {
async fn next_message(&mut self) -> StorageResult<Option<Vec<u8>>>;
}
#[async_trait]
pub trait Migrator: Send + Sync {
async fn migrate(&self) -> StorageResult<usize>;
async fn rollback(&self) -> StorageResult<()>;
async fn applied_migrations(&self) -> StorageResult<Vec<Migration>>;
async fn pending_migrations(&self) -> StorageResult<Vec<Migration>>;
}
#[derive(Debug, Clone)]
pub struct Migration {
pub id: String,
pub name: String,
pub applied_at: Option<DateTime<Utc>>,
pub checksum: String,
}
#[async_trait]
pub trait Backup: Send + Sync {
async fn create_backup(&self, path: &str) -> StorageResult<BackupMetadata>;
async fn restore_backup(&self, path: &str) -> StorageResult<()>;
async fn list_backups(&self, directory: &str) -> StorageResult<Vec<BackupMetadata>>;
async fn delete_backup(&self, path: &str) -> StorageResult<()>;
}
#[derive(Debug, Clone)]
pub struct BackupMetadata {
pub path: String,
pub created_at: DateTime<Utc>,
pub size_bytes: u64,
pub checksum: String,
}