1
0
mirror of https://git.ngram.ca/OpenJam/rc-servers synced 2026-08-23 23:08:52 +00:00
Files
ojrc/rc_services_room/src/user_service.rs
2026-03-12 22:44:04 -04:00

83 lines
2.7 KiB
Rust

pub struct UserMesh {
online_users: tokio::sync::RwLock<std::collections::HashMap<String, UserHandle>>,
}
struct UserHandle {
emitter: polariton_server::events::WeakEventEmitter,
is_alive: std::sync::atomic::AtomicBool,
}
impl UserMesh {
pub fn new() -> Self {
Self {
online_users: tokio::sync::RwLock::new(std::collections::HashMap::new()),
}
}
pub async fn user_count(&self) -> usize {
self.online_users.read().await.values()
.filter(|u| u.is_alive.load(std::sync::atomic::Ordering::Relaxed))
.count()
}
/// returns whether the user was replaced (true) or new (false)
pub async fn add_user(
&self,
public_id: String,
emitter: polariton_server::events::WeakEventEmitter,
) -> bool {
let handle = UserHandle {
emitter,
is_alive: std::sync::atomic::AtomicBool::new(true),
};
self.online_users.write().await
.insert(public_id, handle)
.is_some()
}
/// returns whether the user existing (true) or not (false)
pub async fn remove_user(
&self,
public_id: String,
) -> bool {
self.online_users.write().await
.remove(&public_id)
.is_some()
}
pub async fn broadcast_event_to(&self, public_ids: impl std::iter::Iterator<Item = &str>, event: impl polariton_server::events::IntoEvent<()> + Clone) -> bool {
let user_lock = self.online_users.read().await;
let mut total_success = true;
for public_id in public_ids {
let is_success = if let Some(user_handle) = user_lock.get(public_id) {
let is_success = user_handle.emitter.emit(event.clone());
user_handle.is_alive.swap(is_success, std::sync::atomic::Ordering::SeqCst);
is_success
} else {
false
};
total_success &= is_success;
}
total_success
}
pub async fn send_event_to(&self, public_id: &str, event: impl polariton_server::events::IntoEvent<()>) -> bool {
let user_lock = self.online_users.read().await;
if let Some(user_handle) = user_lock.get(public_id) {
let is_success = user_handle.emitter.emit(event);
user_handle.is_alive.swap(is_success, std::sync::atomic::Ordering::SeqCst);
is_success
} else {
false
}
}
pub async fn is_user_online(&self, public_id: &str) -> bool {
if let Some(user) = self.online_users.read().await.get(public_id) {
user.is_alive.load(std::sync::atomic::Ordering::Relaxed)
} else {
false
}
}
}