use dashmap::DashMap;
use std::sync::Arc;
use tokio::sync::RwLock;
use yrs::sync::Awareness;
use yrs::Doc;
use yrs_warp::AwarenessRef;
#[derive(Default, Debug)]
pub struct YrsManager {
awareness_refs: DashMap<String, AwarenessRef>,
}
impl YrsManager {
pub fn new() -> Self {
Self::default()
}
pub fn get_or_create_awareness(
&self,
room_id: &str,
) -> AwarenessRef {
if let Some(awareness_ref) = self.awareness_refs.get(room_id) {
return awareness_ref.clone();
}
let doc: Doc = Doc::new();
let awareness = Awareness::new(doc);
let awareness_ref = Arc::new(RwLock::new(awareness));
self.awareness_refs.insert(room_id.to_string(), awareness_ref.clone());
awareness_ref
}
pub fn get_awareness_ref(
&self,
room_id: &str,
) -> Option<AwarenessRef> {
self.awareness_refs.get(room_id).map(|r| r.value().clone())
}
pub fn room_exists(
&self,
room_id: &str,
) -> bool {
self.awareness_refs.contains_key(room_id)
}
pub fn get_active_rooms(&self) -> Vec<String> {
self.awareness_refs.iter().map(|entry| entry.key().clone()).collect()
}
pub fn room_count(&self) -> usize {
self.awareness_refs.len()
}
pub async fn remove_room(
&self,
room_id: &str,
) -> Option<AwarenessRef> {
tracing::info!("🔄 移除房间: '{}'", room_id);
if let Some((_, awareness_ref)) = self.awareness_refs.remove(room_id) {
tracing::info!("🔄 房间 '{}' 成功 removed", room_id);
Some(awareness_ref)
} else {
tracing::warn!("🔄 尝试移除不存在的房间: '{}'", room_id);
None
}
}
pub async fn force_cleanup_room(
&self,
room_id: &str,
) -> bool {
tracing::warn!("🔄 强制清理房间: '{}'", room_id);
if let Some((_, awareness_ref)) = self.awareness_refs.remove(room_id) {
if let Ok(mut awareness) = awareness_ref.try_write() {
awareness.clean_local_state();
tracing::info!("房间 '{}' 强制清理完成", room_id);
true
} else {
tracing::error!("🔄 获取写锁失败");
false
}
} else {
tracing::warn!("🔄 房间 '{}' 不存在", room_id);
false
}
}
pub async fn remove_rooms(
&self,
room_ids: &[String],
) -> Vec<String> {
let mut removed_rooms = Vec::new();
for room_id in room_ids {
if self.remove_room(room_id).await.is_some() {
removed_rooms.push(room_id.clone());
}
}
tracing::info!(
"🔄 批量移除 {} 个房间 out of {} rooms",
removed_rooms.len(),
room_ids.len()
);
removed_rooms
}
pub async fn shutdown_all_rooms(&self) {
tracing::info!("🔄 关闭所有 {} 个房间", self.awareness_refs.len());
let all_rooms: Vec<String> = self
.awareness_refs
.iter()
.map(|entry| entry.key().clone())
.collect();
for room_id in all_rooms {
self.remove_room(&room_id).await;
}
tracing::info!("🔄 所有房间已关闭");
}
}