refactor(tests): reformat code and update dependency management
- Reorganized import statements in adapter tests for better readability - Replaced or_insert_with(Vec::new) with or_default() in test closures - Updated Cargo.lock with new dependency versions and checksums - Added TLS features to tonic dependency configuration - Included sqlx, chrono, and uuid dependencies with specific features - Added jsonwebtoken and arc-swap as project dependencies - Reformatted assertion statements to comply with line length limits - Adjusted base64 import order in engine codec module - Updated protobuf include statement formatting
This commit is contained in:
+148
-21
@@ -4,12 +4,13 @@ use std::sync::Arc;
|
||||
use dashmap::DashMap;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
use crate::socket::adapter::{Adapter, BroadcastOptions, BroadcastFlags};
|
||||
use crate::socket::adapter::{Adapter, BroadcastFlags, BroadcastOptions};
|
||||
use crate::socket::packet::Packet;
|
||||
use crate::socket::socket::Socket;
|
||||
|
||||
pub type EventHandler = Arc<dyn Fn(&Socket, &serde_json::Value) + Send + Sync>;
|
||||
type ConnectHandler = Arc<dyn Fn(&Socket, Option<&serde_json::Value>) -> Result<(), String> + Send + Sync>;
|
||||
pub type EventHandler = Arc<dyn Fn(Arc<Socket>, &serde_json::Value) + Send + Sync>;
|
||||
type ConnectHandler =
|
||||
Arc<dyn Fn(&Socket, Option<&serde_json::Value>) -> Result<(), String> + Send + Sync>;
|
||||
|
||||
pub struct Namespace {
|
||||
pub path: String,
|
||||
@@ -19,6 +20,8 @@ pub struct Namespace {
|
||||
engine_to_socket: DashMap<String, String>,
|
||||
handlers: RwLock<HashMap<String, Vec<EventHandler>>>,
|
||||
connect_handler: RwLock<Option<ConnectHandler>>,
|
||||
rooms: DashMap<String, HashSet<String>>,
|
||||
socket_rooms: DashMap<String, HashSet<String>>,
|
||||
pub(crate) adapter: RwLock<Option<Arc<dyn Adapter>>>,
|
||||
}
|
||||
|
||||
@@ -30,6 +33,8 @@ impl Namespace {
|
||||
engine_to_socket: DashMap::new(),
|
||||
handlers: RwLock::new(HashMap::new()),
|
||||
connect_handler: RwLock::new(None),
|
||||
rooms: DashMap::new(),
|
||||
socket_rooms: DashMap::new(),
|
||||
adapter: RwLock::new(None),
|
||||
}
|
||||
}
|
||||
@@ -40,11 +45,15 @@ impl Namespace {
|
||||
}
|
||||
|
||||
/// Add a socket to this namespace. Returns Err if the connect handler rejects.
|
||||
pub async fn add_socket(&self, socket: Arc<Socket>) -> Result<(), String> {
|
||||
pub async fn add_socket(
|
||||
&self,
|
||||
socket: Arc<Socket>,
|
||||
auth_data: Option<&serde_json::Value>,
|
||||
) -> Result<(), String> {
|
||||
// Run connect handler before adding to storage
|
||||
let handler = self.connect_handler.read().await;
|
||||
if let Some(ref h) = *handler {
|
||||
h(&socket, None)?;
|
||||
h(&socket, auth_data)?;
|
||||
}
|
||||
drop(handler);
|
||||
|
||||
@@ -53,10 +62,10 @@ impl Namespace {
|
||||
|
||||
// Register with adapter (socket_sid → engine_sid mapping)
|
||||
let adapter = self.adapter.read().await;
|
||||
if let Some(ref adapter) = *adapter {
|
||||
if let Err(e) = adapter.register(&socket_sid, &engine_sid, &self.path).await {
|
||||
tracing::warn!("Adapter register error for socket {}: {}", socket_sid, e);
|
||||
}
|
||||
if let Some(ref adapter) = *adapter
|
||||
&& let Err(e) = adapter.register(&socket_sid, &engine_sid, &self.path).await
|
||||
{
|
||||
tracing::warn!("Adapter register error for socket {}: {}", socket_sid, e);
|
||||
}
|
||||
|
||||
// Store socket by socket_sid, plus reverse index
|
||||
@@ -69,12 +78,13 @@ impl Namespace {
|
||||
pub async fn remove_socket_by_sid(&self, socket_sid: &str) {
|
||||
if let Some((_, socket)) = self.sockets.remove(socket_sid) {
|
||||
self.engine_to_socket.remove(&socket.engine_sid);
|
||||
self.remove_socket_from_local_rooms(socket_sid);
|
||||
|
||||
let adapter = self.adapter.read().await;
|
||||
if let Some(ref adapter) = *adapter {
|
||||
if let Err(e) = adapter.del_all(socket_sid, &self.path).await {
|
||||
tracing::warn!("Adapter del_all error for socket {}: {}", socket_sid, e);
|
||||
}
|
||||
if let Some(ref adapter) = *adapter
|
||||
&& let Err(e) = adapter.del_all(socket_sid, &self.path).await
|
||||
{
|
||||
tracing::warn!("Adapter del_all error for socket {}: {}", socket_sid, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -130,7 +140,12 @@ impl Namespace {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn emit_to_room(&self, room: &str, event: impl Into<String>, data: serde_json::Value) {
|
||||
pub async fn emit_to_room(
|
||||
&self,
|
||||
room: &str,
|
||||
event: impl Into<String>,
|
||||
data: serde_json::Value,
|
||||
) {
|
||||
let event_name = event.into();
|
||||
let packet = Packet::event(&self.path, serde_json::json!([event_name, data]), None);
|
||||
|
||||
@@ -145,20 +160,64 @@ impl Namespace {
|
||||
tracing::warn!("Adapter broadcast to room error: {}", e);
|
||||
}
|
||||
} else {
|
||||
self.emit_local(&packet);
|
||||
self.emit_local_to_room(&packet, room, &HashSet::new());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn emit_local(&self, packet: &Packet) {
|
||||
for entry in self.sockets.iter() {
|
||||
let socket = entry.value();
|
||||
if socket.send_packet(packet).is_err() {
|
||||
tracing::warn!("Failed to send event to socket {}", socket.sid);
|
||||
self.send_local_packet(entry.value(), packet);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn emit_local_filtered(&self, packet: &Packet, opts: &BroadcastOptions) {
|
||||
if opts.rooms.is_empty() {
|
||||
for entry in self.sockets.iter() {
|
||||
if !opts.except.contains(entry.key()) {
|
||||
self.send_local_packet(entry.value(), packet);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
let mut target_sids = HashSet::new();
|
||||
for room in &opts.rooms {
|
||||
if let Some(room_sids) = self.rooms.get(room) {
|
||||
target_sids.extend(room_sids.value().iter().cloned());
|
||||
}
|
||||
}
|
||||
|
||||
for sid in target_sids {
|
||||
if opts.except.contains(&sid) {
|
||||
continue;
|
||||
}
|
||||
if let Some(socket) = self.get_socket(&sid) {
|
||||
self.send_local_packet(&socket, packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn emit_to(&self, socket_sid: &str, event: impl Into<String>, data: serde_json::Value) {
|
||||
fn emit_local_to_room(&self, packet: &Packet, room: &str, except: &HashSet<String>) {
|
||||
let opts = BroadcastOptions {
|
||||
rooms: HashSet::from([room.to_string()]),
|
||||
except: except.clone(),
|
||||
flags: BroadcastFlags::default(),
|
||||
};
|
||||
self.emit_local_filtered(packet, &opts);
|
||||
}
|
||||
|
||||
fn send_local_packet(&self, socket: &Socket, packet: &Packet) {
|
||||
if socket.send_packet(packet).is_err() {
|
||||
tracing::warn!("Failed to send event to socket {}", socket.sid);
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn emit_to(
|
||||
&self,
|
||||
socket_sid: &str,
|
||||
event: impl Into<String>,
|
||||
data: serde_json::Value,
|
||||
) {
|
||||
if let Some(socket) = self.get_socket(socket_sid) {
|
||||
let event_name = event.into();
|
||||
let packet = Packet::event(&self.path, serde_json::json!([event_name, data]), None);
|
||||
@@ -168,11 +227,79 @@ impl Namespace {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn handle_event(&self, socket: &Socket, event: &str, data: &serde_json::Value) {
|
||||
pub async fn handle_event(&self, socket: Arc<Socket>, event: &str, data: &serde_json::Value) {
|
||||
let handlers = self.handlers.read().await;
|
||||
if let Some(event_handlers) = handlers.get(event) {
|
||||
for handler in event_handlers {
|
||||
handler(socket, data);
|
||||
handler(Arc::clone(&socket), data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn join_room(&self, socket_sid: &str, room: &str) -> crate::ImksResult<()> {
|
||||
if !self.sockets.contains_key(socket_sid) {
|
||||
return Err(crate::ImksError::SocketNotFound(socket_sid.to_string()));
|
||||
}
|
||||
|
||||
self.rooms
|
||||
.entry(room.to_string())
|
||||
.or_default()
|
||||
.value_mut()
|
||||
.insert(socket_sid.to_string());
|
||||
self.socket_rooms
|
||||
.entry(socket_sid.to_string())
|
||||
.or_default()
|
||||
.value_mut()
|
||||
.insert(room.to_string());
|
||||
|
||||
let adapter = self.adapter.read().await;
|
||||
if let Some(ref adapter) = *adapter
|
||||
&& let Err(e) = adapter.add(socket_sid, room, &self.path).await
|
||||
{
|
||||
self.remove_local_room(socket_sid, room);
|
||||
return Err(e.into());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn leave_room(&self, socket_sid: &str, room: &str) -> crate::ImksResult<()> {
|
||||
let adapter = self.adapter.read().await;
|
||||
if let Some(ref adapter) = *adapter {
|
||||
adapter.del(socket_sid, room, &self.path).await?;
|
||||
}
|
||||
|
||||
self.remove_local_room(socket_sid, room);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn remove_local_room(&self, socket_sid: &str, room: &str) {
|
||||
if let Some(mut sids) = self.rooms.get_mut(room) {
|
||||
sids.value_mut().remove(socket_sid);
|
||||
if sids.value().is_empty() {
|
||||
drop(sids);
|
||||
self.rooms.remove(room);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(mut rooms) = self.socket_rooms.get_mut(socket_sid) {
|
||||
rooms.value_mut().remove(room);
|
||||
if rooms.value().is_empty() {
|
||||
drop(rooms);
|
||||
self.socket_rooms.remove(socket_sid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn remove_socket_from_local_rooms(&self, socket_sid: &str) {
|
||||
if let Some((_, rooms)) = self.socket_rooms.remove(socket_sid) {
|
||||
for room in rooms {
|
||||
if let Some(mut sids) = self.rooms.get_mut(&room) {
|
||||
sids.value_mut().remove(socket_sid);
|
||||
if sids.value().is_empty() {
|
||||
drop(sids);
|
||||
self.rooms.remove(&room);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user