use crate::RragResult;
use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum MemoryValue {
String(String),
Integer(i64),
Float(f64),
Boolean(bool),
Json(serde_json::Value),
Bytes(Vec<u8>),
List(Vec<MemoryValue>),
Map(HashMap<String, MemoryValue>),
}
impl MemoryValue {
pub fn as_string(&self) -> Option<&str> {
match self {
MemoryValue::String(s) => Some(s),
_ => None,
}
}
pub fn as_integer(&self) -> Option<i64> {
match self {
MemoryValue::Integer(i) => Some(*i),
_ => None,
}
}
pub fn as_float(&self) -> Option<f64> {
match self {
MemoryValue::Float(f) => Some(*f),
_ => None,
}
}
pub fn as_boolean(&self) -> Option<bool> {
match self {
MemoryValue::Boolean(b) => Some(*b),
_ => None,
}
}
pub fn as_json(&self) -> Option<&serde_json::Value> {
match self {
MemoryValue::Json(j) => Some(j),
_ => None,
}
}
pub fn as_bytes(&self) -> Option<&[u8]> {
match self {
MemoryValue::Bytes(b) => Some(b),
_ => None,
}
}
}
impl From<String> for MemoryValue {
fn from(s: String) -> Self {
MemoryValue::String(s)
}
}
impl From<&str> for MemoryValue {
fn from(s: &str) -> Self {
MemoryValue::String(s.to_string())
}
}
impl From<i64> for MemoryValue {
fn from(i: i64) -> Self {
MemoryValue::Integer(i)
}
}
impl From<f64> for MemoryValue {
fn from(f: f64) -> Self {
MemoryValue::Float(f)
}
}
impl From<bool> for MemoryValue {
fn from(b: bool) -> Self {
MemoryValue::Boolean(b)
}
}
impl From<serde_json::Value> for MemoryValue {
fn from(j: serde_json::Value) -> Self {
MemoryValue::Json(j)
}
}
impl From<Vec<u8>> for MemoryValue {
fn from(b: Vec<u8>) -> Self {
MemoryValue::Bytes(b)
}
}
#[derive(Debug, Clone, Default)]
pub struct MemoryQuery {
pub key_pattern: Option<String>,
pub namespace: Option<String>,
pub limit: Option<usize>,
pub offset: Option<usize>,
pub sort_order: Option<SortOrder>,
}
#[derive(Debug, Clone)]
pub enum SortOrder {
KeyAsc,
KeyDesc,
CreatedAsc,
CreatedDesc,
}
impl MemoryQuery {
pub fn new() -> Self {
Self::default()
}
pub fn with_pattern(mut self, pattern: impl Into<String>) -> Self {
self.key_pattern = Some(pattern.into());
self
}
pub fn with_namespace(mut self, namespace: impl Into<String>) -> Self {
self.namespace = Some(namespace.into());
self
}
pub fn with_limit(mut self, limit: usize) -> Self {
self.limit = Some(limit);
self
}
pub fn with_offset(mut self, offset: usize) -> Self {
self.offset = Some(offset);
self
}
}
#[async_trait]
pub trait Memory: Send + Sync {
fn backend_name(&self) -> &str;
async fn set(&self, key: &str, value: MemoryValue) -> RragResult<()>;
async fn get(&self, key: &str) -> RragResult<Option<MemoryValue>>;
async fn delete(&self, key: &str) -> RragResult<bool>;
async fn exists(&self, key: &str) -> RragResult<bool>;
async fn keys(&self, query: &MemoryQuery) -> RragResult<Vec<String>>;
async fn mget(&self, keys: &[String]) -> RragResult<Vec<Option<MemoryValue>>>;
async fn mset(&self, pairs: &[(String, MemoryValue)]) -> RragResult<()>;
async fn mdelete(&self, keys: &[String]) -> RragResult<usize>;
async fn clear(&self, namespace: Option<&str>) -> RragResult<()>;
async fn count(&self, namespace: Option<&str>) -> RragResult<usize>;
async fn health_check(&self) -> RragResult<bool>;
async fn stats(&self) -> RragResult<MemoryStats>;
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MemoryStats {
pub total_keys: usize,
pub memory_bytes: u64,
pub backend_type: String,
pub namespace_count: usize,
pub last_updated: chrono::DateTime<chrono::Utc>,
pub extra: HashMap<String, serde_json::Value>,
}