重构流程引擎核心组件,引入执行器接口Executor替代原有TaskComponent,优化节点配置映射逻辑: 1. 新增mappers模块集中处理节点配置提取 2. 为存储层添加Storage trait抽象 3. 移除对ctx魔法字段的依赖,直接传递节点信息 4. 增加构建器模式支持引擎创建 5. 完善DSL解析的输入校验 同时标记部分未使用代码为allow(dead_code)
159 lines
6.0 KiB
Rust
159 lines
6.0 KiB
Rust
use redis::{Client, AsyncCommands};
|
|
use redis::aio::ConnectionManager;
|
|
use once_cell::sync::OnceCell;
|
|
use crate::error::AppError;
|
|
|
|
pub type RedisPool = ConnectionManager;
|
|
|
|
static REDIS_POOL: OnceCell<RedisPool> = OnceCell::new();
|
|
|
|
/// 初始化Redis连接池
|
|
pub async fn init_redis() -> Result<RedisPool, AppError> {
|
|
let redis_url = std::env::var("REDIS_URL")
|
|
.unwrap_or_else(|_| "redis://:123456@127.0.0.1:6379/9".into());
|
|
|
|
tracing::info!("Connecting to Redis at: {}", redis_url.replace(":123456", ":***"));
|
|
|
|
let client = Client::open(redis_url)
|
|
.map_err(|e| AppError::Anyhow(anyhow::anyhow!("Failed to create Redis client: {}", e)))?;
|
|
|
|
let manager = ConnectionManager::new(client).await
|
|
.map_err(|e| AppError::Anyhow(anyhow::anyhow!("Failed to create Redis connection manager: {}", e)))?;
|
|
|
|
tracing::info!("Redis connection established successfully");
|
|
Ok(manager)
|
|
}
|
|
|
|
/// 获取Redis连接池
|
|
pub fn get_redis() -> Result<&'static RedisPool, AppError> {
|
|
REDIS_POOL.get().ok_or_else(|| AppError::Anyhow(anyhow::anyhow!("Redis pool not initialized")))
|
|
}
|
|
|
|
/// 设置Redis连接池
|
|
pub fn set_redis_pool(pool: RedisPool) -> Result<(), AppError> {
|
|
REDIS_POOL.set(pool)
|
|
.map_err(|_| AppError::Anyhow(anyhow::anyhow!("Redis pool already initialized")))
|
|
}
|
|
|
|
/// Redis工具函数
|
|
pub struct RedisHelper;
|
|
|
|
impl RedisHelper {
|
|
/// 设置带过期时间的键值对
|
|
pub async fn set_ex(key: &str, value: &str, expire_seconds: u64) -> Result<(), AppError> {
|
|
let mut conn = get_redis()?.clone();
|
|
tracing::debug!("Redis SET_EX: key={}, value_len={}, expire_seconds={}", key, value.len(), expire_seconds);
|
|
let _: String = conn.set_ex(key, value, expire_seconds).await
|
|
.map_err(|e| {
|
|
tracing::error!("Redis set_ex failed for key {}: {}", key, e);
|
|
AppError::Anyhow(anyhow::anyhow!("Redis set_ex failed: {}", e))
|
|
})?;
|
|
tracing::debug!("Redis SET_EX successful for key: {}", key);
|
|
Ok(())
|
|
}
|
|
|
|
/// 获取键值
|
|
pub async fn get(key: &str) -> Result<Option<String>, AppError> {
|
|
let mut conn = get_redis()?.clone();
|
|
let result: Option<String> = conn.get(key).await
|
|
.map_err(|e| AppError::Anyhow(anyhow::anyhow!("Redis get failed: {}", e)))?;
|
|
Ok(result)
|
|
}
|
|
|
|
/// 删除键
|
|
#[allow(dead_code)]
|
|
pub async fn del(key: &str) -> Result<(), AppError> {
|
|
let mut conn = get_redis()?.clone();
|
|
let _: i32 = conn.del(key).await
|
|
.map_err(|e| AppError::Anyhow(anyhow::anyhow!("Redis del failed: {}", e)))?;
|
|
Ok(())
|
|
}
|
|
|
|
/// 检查键是否存在
|
|
#[allow(dead_code)]
|
|
pub async fn exists(key: &str) -> Result<bool, AppError> {
|
|
let mut conn = get_redis()?.clone();
|
|
let result: bool = conn.exists(key).await
|
|
.map_err(|e| AppError::Anyhow(anyhow::anyhow!("Redis exists failed: {}", e)))?;
|
|
Ok(result)
|
|
}
|
|
|
|
/// 设置键的过期时间
|
|
#[allow(dead_code)]
|
|
pub async fn expire(key: &str, seconds: u64) -> Result<(), AppError> {
|
|
let mut conn = get_redis()?.clone();
|
|
let _: bool = conn.expire(key, seconds as i64).await
|
|
.map_err(|e| AppError::Anyhow(anyhow::anyhow!("Redis expire failed: {}", e)))?;
|
|
Ok(())
|
|
}
|
|
|
|
/// 删除用户相关的所有token
|
|
pub async fn del_user_tokens(user_id: i64) -> Result<(), AppError> {
|
|
let pattern = format!("token:*:user:{}", user_id);
|
|
let mut conn = get_redis()?.clone();
|
|
|
|
// 获取匹配的键
|
|
let keys: Vec<String> = conn.keys(&pattern).await
|
|
.map_err(|e| AppError::Anyhow(anyhow::anyhow!("Redis keys failed: {}", e)))?;
|
|
|
|
// 删除所有匹配的键
|
|
if !keys.is_empty() {
|
|
let _: i32 = conn.del(&keys).await
|
|
.map_err(|e| AppError::Anyhow(anyhow::anyhow!("Redis del multiple failed: {}", e)))?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
/// Token相关的Redis操作
|
|
pub struct TokenRedis;
|
|
|
|
impl TokenRedis {
|
|
/// 存储访问token
|
|
pub async fn store_access_token(token: &str, user_id: i64, expire_seconds: u64) -> Result<(), AppError> {
|
|
let key = format!("token:access:user:{}", user_id);
|
|
tracing::info!("Storing access token for user {} with key: {}, expires in {} seconds", user_id, key, expire_seconds);
|
|
RedisHelper::set_ex(&key, token, expire_seconds).await
|
|
}
|
|
|
|
/// 存储刷新token
|
|
pub async fn store_refresh_token(token: &str, user_id: i64, expire_seconds: u64) -> Result<(), AppError> {
|
|
let key = format!("token:refresh:user:{}", user_id);
|
|
tracing::info!("Storing refresh token for user {} with key: {}, expires in {} seconds", user_id, key, expire_seconds);
|
|
RedisHelper::set_ex(&key, token, expire_seconds).await
|
|
}
|
|
|
|
/// 验证访问token
|
|
pub async fn validate_access_token(token: &str, user_id: i64) -> Result<bool, AppError> {
|
|
let key = format!("token:access:user:{}", user_id);
|
|
let stored_token = RedisHelper::get(&key).await?;
|
|
Ok(stored_token.as_deref() == Some(token))
|
|
}
|
|
|
|
/// 验证刷新token
|
|
pub async fn validate_refresh_token(token: &str, user_id: i64) -> Result<bool, AppError> {
|
|
let key = format!("token:refresh:user:{}", user_id);
|
|
let stored_token = RedisHelper::get(&key).await?;
|
|
Ok(stored_token.as_deref() == Some(token))
|
|
}
|
|
|
|
/// 删除用户的访问token
|
|
#[allow(dead_code)]
|
|
pub async fn revoke_access_token(user_id: i64) -> Result<(), AppError> {
|
|
let key = format!("token:access:user:{}", user_id);
|
|
RedisHelper::del(&key).await
|
|
}
|
|
|
|
/// 删除用户的刷新token
|
|
#[allow(dead_code)]
|
|
pub async fn revoke_refresh_token(user_id: i64) -> Result<(), AppError> {
|
|
let key = format!("token:refresh:user:{}", user_id);
|
|
RedisHelper::del(&key).await
|
|
}
|
|
|
|
/// 删除用户的所有token
|
|
pub async fn revoke_all_tokens(user_id: i64) -> Result<(), AppError> {
|
|
RedisHelper::del_user_tokens(user_id).await
|
|
}
|
|
} |