102 lines
3.3 KiB
Rust
102 lines
3.3 KiB
Rust
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(())
|
|
}
|
|
}
|