use async_trait::async_trait;
use serde::Serialize;
use serde::de::DeserializeOwned;
use std::sync::Arc;
use std::time::Duration;
use crate::error::CacheError;
use crate::cache::Cache;
use super::manager::MemoryManager;
const MAX_KEY_LENGTH: usize = 200;
pub struct PluginMemoryCache {
manager: Arc<MemoryManager>,
plugin_id: String,
namespace: String,
}
impl PluginMemoryCache {
pub(crate) fn new(manager: Arc<MemoryManager>, plugin_id: String) -> Self {
let system_name = manager.system_name();
let capacity = system_name.len() + plugin_id.len() + 9; let mut namespace = String::with_capacity(capacity);
namespace.push_str(system_name);
namespace.push_str(":plugin:");
namespace.push_str(&plugin_id);
namespace.push(':');
Self {
manager,
plugin_id,
namespace,
}
}
fn build_key(&self, business_key: &str) -> Result<String, CacheError> {
self.validate_business_key(business_key)?;
let capacity = self.namespace.len() + business_key.len();
let mut full_key = String::with_capacity(capacity);
full_key.push_str(&self.namespace);
full_key.push_str(business_key);
Ok(full_key)
}
fn validate_business_key(&self, key: &str) -> Result<(), CacheError> {
if key.is_empty() {
return Err(CacheError::InvalidKey("Key 不能为空".to_string()));
}
if key.len() > MAX_KEY_LENGTH {
return Err(CacheError::InvalidKey(
format!("Key 长度不能超过 {} 字符", MAX_KEY_LENGTH),
));
}
if key.as_bytes().windows(7).any(|w| w == b"plugin:") {
return Err(CacheError::InvalidKey(
"Key 不能包含命名空间前缀".to_string(),
));
}
if !key.as_bytes().iter().all(|&b| {
matches!(b, b'a'..=b'z' | b'A'..=b'Z' | b'0'..=b'9' | b'_' | b'-' | b':')
}) {
return Err(CacheError::InvalidKey(
"Key 包含非法字符,只允许字母、数字、下划线、连字符、冒号".to_string(),
));
}
Ok(())
}
fn verify_permission(&self, full_key: &str) -> Result<(), CacheError> {
if !full_key.starts_with(&self.namespace) {
return Err(CacheError::PermissionDenied(
"Key 不属于当前插件".to_string(),
));
}
Ok(())
}
}
#[async_trait]
impl Cache for PluginMemoryCache {
async fn get<T>(&self, key: &str) -> Result<Option<T>, CacheError>
where
T: DeserializeOwned,
{
let full_key = self.build_key(key)?;
let cache = self.manager.get_cache();
let json_value = cache.get(&full_key).await;
match json_value {
Some(json) => {
let value: T = serde_json::from_str(&json)
.map_err(|e| CacheError::DeserializationFailed(e.to_string()))?;
Ok(Some(value))
}
None => Ok(None),
}
}
async fn set<T>(&self, key: &str, value: &T, _ttl: Option<Duration>) -> Result<(), CacheError>
where
T: Serialize + Sync,
{
let full_key = self.build_key(key)?;
let json_value = serde_json::to_string(value)
.map_err(|e| CacheError::SerializationFailed(e.to_string()))?;
let cache = self.manager.get_cache();
cache.insert(full_key.clone(), json_value).await;
self.manager
.add_key_to_index(&self.plugin_id, &full_key);
Ok(())
}
async fn delete(&self, key: &str) -> Result<bool, CacheError> {
let full_key = self.build_key(key)?;
self.verify_permission(&full_key)?;
let cache = self.manager.get_cache();
let deleted = cache.remove(&full_key).await.is_some();
if deleted {
self.manager
.remove_key_from_index(&self.plugin_id, &full_key);
}
Ok(deleted)
}
async fn exists(&self, key: &str) -> Result<bool, CacheError> {
let full_key = self.build_key(key)?;
let cache = self.manager.get_cache();
let exists = cache.get(&full_key).await.is_some();
Ok(exists)
}
async fn expire(&self, key: &str, _ttl: Duration) -> Result<bool, CacheError> {
let full_key = self.build_key(key)?;
let cache = self.manager.get_cache();
if let Some(value) = cache.get(&full_key).await {
cache.insert(full_key, value).await;
Ok(true)
} else {
Ok(false)
}
}
async fn ttl(&self, key: &str) -> Result<Option<Duration>, CacheError> {
let full_key = self.build_key(key)?;
let cache = self.manager.get_cache();
if cache.get(&full_key).await.is_some() {
Ok(None)
} else {
Ok(None) }
}
async fn clear(&self) -> Result<u64, CacheError> {
self.manager.clear_plugin(&self.plugin_id).await
}
async fn clear_module(&self, module: &str) -> Result<u64, CacheError> {
self.manager.clear_module(&self.plugin_id, module).await
}
}