feat: init

This commit is contained in:
zhenyi
2026-06-07 11:30:56 +08:00
commit 563381c1ca
361 changed files with 41327 additions and 0 deletions
+101
View File
@@ -0,0 +1,101 @@
use std::collections::HashMap;
use uuid::Uuid;
use crate::cache::redis::AppRedis;
use crate::error::{AppError, AppResult};
use ::redis::Cmd;
use super::redis_keys::*;
pub struct ReconnectManager {
redis: AppRedis,
}
impl ReconnectManager {
pub fn new(redis: AppRedis) -> Self {
Self { redis }
}
pub fn save_read_position(&self, user_id: Uuid, channel_id: Uuid, seq: i64) -> AppResult<()> {
let key = format!("{WS_RECONNECT_PREFIX}{user_id}:{channel_id}");
let mut conn = self.redis.get_connection()?;
Cmd::new()
.arg("SETEX")
.arg(&key)
.arg(WS_RECONNECT_STATE_TTL_SECS)
.arg(seq.to_string())
.query::<()>(&mut *conn.inner_mut())
.map_err(AppError::Redis)?;
Ok(())
}
pub fn save_read_positions(
&self,
user_id: Uuid,
positions: &HashMap<Uuid, i64>,
) -> AppResult<()> {
let mut conn = self.redis.get_connection()?;
for (channel_id, seq) in positions {
let key = format!("{WS_RECONNECT_PREFIX}{user_id}:{channel_id}");
Cmd::new()
.arg("SETEX")
.arg(&key)
.arg(WS_RECONNECT_STATE_TTL_SECS)
.arg(seq.to_string())
.query::<()>(&mut *conn.inner_mut())
.map_err(AppError::Redis)?;
}
Ok(())
}
pub fn get_last_seq(&self, user_id: Uuid, channel_id: Uuid) -> AppResult<Option<i64>> {
let key = format!("{WS_RECONNECT_PREFIX}{user_id}:{channel_id}");
let mut conn = self.redis.get_connection()?;
let val: Option<String> = Cmd::new()
.arg("GET")
.arg(&key)
.query(&mut *conn.inner_mut())
.map_err(AppError::Redis)?;
Ok(val.and_then(|v| v.parse().ok()))
}
pub fn get_all_positions(&self, user_id: Uuid) -> AppResult<HashMap<Uuid, i64>> {
let pattern = format!("{WS_RECONNECT_PREFIX}{user_id}:*");
let mut conn = self.redis.get_connection()?;
let keys: Vec<String> = Cmd::new()
.arg("KEYS")
.arg(&pattern)
.query(&mut *conn.inner_mut())
.map_err(AppError::Redis)?;
let mut result = HashMap::new();
let prefix_len = format!("{WS_RECONNECT_PREFIX}{user_id}:").len();
for key in &keys {
if let Some(channel_str) = key.get(prefix_len..)
&& let Ok(channel_id) = channel_str.parse::<Uuid>()
{
let val: Option<String> = Cmd::new()
.arg("GET")
.arg(key)
.query(&mut *conn.inner_mut())
.map_err(AppError::Redis)?;
if let Some(v) = val
&& let Ok(seq) = v.parse::<i64>()
{
result.insert(channel_id, seq);
}
}
}
Ok(result)
}
pub fn cleanup_channel(&self, user_id: Uuid, channel_id: Uuid) -> AppResult<()> {
let key = format!("{WS_RECONNECT_PREFIX}{user_id}:{channel_id}");
let mut conn = self.redis.get_connection()?;
let _ = Cmd::new()
.arg("DEL")
.arg(&key)
.query::<()>(&mut *conn.inner_mut());
Ok(())
}
}