enhanced websocket handling
This commit is contained in:
@@ -1,52 +1,14 @@
|
|||||||
use rust_socketio::{ClientBuilder, Event, Payload, RawClient};
|
use rust_socketio::ClientBuilder;
|
||||||
use serde_json::json;
|
|
||||||
use tauri::async_runtime;
|
use tauri::async_runtime;
|
||||||
use tracing::{error, info};
|
use tracing::{error, info};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
lock_r, lock_w,
|
lock_r, lock_w,
|
||||||
services::{
|
services::client_config_manager::AppConfig,
|
||||||
client_config_manager::AppConfig, health_manager::close_health_manager_window,
|
|
||||||
scene::open_scene_window,
|
|
||||||
},
|
|
||||||
state::FDOLL,
|
state::FDOLL,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::WS_EVENT;
|
use super::handlers;
|
||||||
|
|
||||||
fn emit_initialize(socket: &RawClient) {
|
|
||||||
if let Err(e) = socket.emit(WS_EVENT::CLIENT_INITIALIZE, json!({})) {
|
|
||||||
error!("Failed to emit client-initialize: {:?}", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn on_connected(_payload: Payload, socket: RawClient) {
|
|
||||||
info!("WebSocket connected. Sending initialization request.");
|
|
||||||
emit_initialize(&socket);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn on_initialized(payload: Payload, _socket: RawClient) {
|
|
||||||
match payload {
|
|
||||||
Payload::Text(values) => {
|
|
||||||
if let Some(first_value) = values.first() {
|
|
||||||
info!("Received initialized event: {:?}", first_value);
|
|
||||||
|
|
||||||
// Mark WebSocket as initialized and reset backoff timer
|
|
||||||
let mut guard = lock_w!(FDOLL);
|
|
||||||
if let Some(clients) = guard.network.clients.as_mut() {
|
|
||||||
clients.is_ws_initialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Connection restored: close health manager and reopen scene
|
|
||||||
close_health_manager_window();
|
|
||||||
open_scene_window();
|
|
||||||
} else {
|
|
||||||
info!("Received initialized event with empty payload");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => error!("Received unexpected payload format for initialized"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn init_ws_client() {
|
pub async fn init_ws_client() {
|
||||||
let app_config = {
|
let app_config = {
|
||||||
@@ -89,62 +51,13 @@ pub async fn build_ws_client(
|
|||||||
.ok_or("Missing API base URL")?;
|
.ok_or("Missing API base URL")?;
|
||||||
|
|
||||||
let client_result = async_runtime::spawn_blocking(move || {
|
let client_result = async_runtime::spawn_blocking(move || {
|
||||||
ClientBuilder::new(api_base_url)
|
let builder = ClientBuilder::new(api_base_url)
|
||||||
.namespace("/")
|
.namespace("/")
|
||||||
.on(
|
.auth(serde_json::json!({ "token": token }));
|
||||||
WS_EVENT::FRIEND_REQUEST_RECEIVED,
|
|
||||||
super::friend::on_friend_request_received,
|
let builder_with_handlers = handlers::register_event_handlers(builder);
|
||||||
)
|
|
||||||
.on(
|
builder_with_handlers.connect()
|
||||||
WS_EVENT::FRIEND_REQUEST_ACCEPTED,
|
|
||||||
super::friend::on_friend_request_accepted,
|
|
||||||
)
|
|
||||||
.on(
|
|
||||||
WS_EVENT::FRIEND_REQUEST_DENIED,
|
|
||||||
super::friend::on_friend_request_denied,
|
|
||||||
)
|
|
||||||
.on(WS_EVENT::UNFRIENDED, super::friend::on_unfriended)
|
|
||||||
.on(
|
|
||||||
WS_EVENT::FRIEND_CURSOR_POSITION,
|
|
||||||
super::friend::on_friend_cursor_position,
|
|
||||||
)
|
|
||||||
.on(
|
|
||||||
WS_EVENT::FRIEND_DISCONNECTED,
|
|
||||||
super::friend::on_friend_disconnected,
|
|
||||||
)
|
|
||||||
.on(
|
|
||||||
WS_EVENT::FRIEND_DOLL_CREATED,
|
|
||||||
super::friend::on_friend_doll_created,
|
|
||||||
)
|
|
||||||
.on(
|
|
||||||
WS_EVENT::FRIEND_DOLL_UPDATED,
|
|
||||||
super::friend::on_friend_doll_updated,
|
|
||||||
)
|
|
||||||
.on(
|
|
||||||
WS_EVENT::FRIEND_DOLL_DELETED,
|
|
||||||
super::friend::on_friend_doll_deleted,
|
|
||||||
)
|
|
||||||
.on(
|
|
||||||
WS_EVENT::FRIEND_ACTIVE_DOLL_CHANGED,
|
|
||||||
super::friend::on_friend_active_doll_changed,
|
|
||||||
)
|
|
||||||
.on(WS_EVENT::DOLL_CREATED, super::doll::on_doll_created)
|
|
||||||
.on(WS_EVENT::DOLL_UPDATED, super::doll::on_doll_updated)
|
|
||||||
.on(WS_EVENT::DOLL_DELETED, super::doll::on_doll_deleted)
|
|
||||||
.on(WS_EVENT::INITIALIZED, on_initialized)
|
|
||||||
.on(
|
|
||||||
WS_EVENT::INTERACTION_RECEIVED,
|
|
||||||
super::interaction::on_interaction_received,
|
|
||||||
)
|
|
||||||
.on(
|
|
||||||
WS_EVENT::INTERACTION_DELIVERY_FAILED,
|
|
||||||
super::interaction::on_interaction_delivery_failed,
|
|
||||||
)
|
|
||||||
// rust-socketio fires Event::Connect on initial connect AND reconnects
|
|
||||||
// so we resend initialization there instead of a dedicated reconnect event.
|
|
||||||
.on(Event::Connect, on_connected)
|
|
||||||
.auth(json!({ "token": token }))
|
|
||||||
.connect()
|
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
|
|||||||
45
src-tauri/src/services/ws/connection.rs
Normal file
45
src-tauri/src/services/ws/connection.rs
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
use rust_socketio::{Payload, RawClient};
|
||||||
|
use tracing::info;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
lock_w,
|
||||||
|
services::health_manager::close_health_manager_window,
|
||||||
|
services::scene::open_scene_window,
|
||||||
|
state::FDOLL,
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::WS_EVENT;
|
||||||
|
|
||||||
|
fn emit_initialize(socket: &RawClient) {
|
||||||
|
if let Err(e) = socket.emit(WS_EVENT::CLIENT_INITIALIZE, serde_json::json!({})) {
|
||||||
|
tracing::error!("Failed to emit client-initialize: {:?}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn on_connected(_payload: Payload, socket: RawClient) {
|
||||||
|
info!("WebSocket connected. Sending initialization request.");
|
||||||
|
emit_initialize(&socket);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn on_initialized(payload: Payload, _socket: RawClient) {
|
||||||
|
match payload {
|
||||||
|
Payload::Text(values) => {
|
||||||
|
if let Some(first_value) = values.first() {
|
||||||
|
info!("Received initialized event: {:?}", first_value);
|
||||||
|
|
||||||
|
// Mark WebSocket as initialized and reset backoff timer
|
||||||
|
let mut guard = lock_w!(FDOLL);
|
||||||
|
if let Some(clients) = guard.network.clients.as_mut() {
|
||||||
|
clients.is_ws_initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connection restored: close health manager and reopen scene
|
||||||
|
close_health_manager_window();
|
||||||
|
open_scene_window();
|
||||||
|
} else {
|
||||||
|
info!("Received initialized event with empty payload");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => tracing::error!("Received unexpected payload format for initialized"),
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -123,43 +123,28 @@ pub fn on_friend_disconnected(payload: Payload, _socket: RawClient) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_friend_doll_created(payload: Payload, _socket: RawClient) {
|
pub fn on_friend_doll_created(payload: Payload, _socket: RawClient) {
|
||||||
match payload {
|
handle_friend_doll_change(WS_EVENT::FRIEND_DOLL_CREATED, payload);
|
||||||
Payload::Text(values) => {
|
|
||||||
// Log raw JSON for now, as requested
|
|
||||||
if let Some(first_value) = values.first() {
|
|
||||||
info!("Received friend-doll-created event: {:?}", first_value);
|
|
||||||
// Future: Trigger re-fetch or emit to frontend
|
|
||||||
} else {
|
|
||||||
info!("Received friend-doll-created event with empty payload");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => error!("Received unexpected payload format for friend-doll-created"),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_friend_doll_updated(payload: Payload, _socket: RawClient) {
|
pub fn on_friend_doll_updated(payload: Payload, _socket: RawClient) {
|
||||||
match payload {
|
handle_friend_doll_change(WS_EVENT::FRIEND_DOLL_UPDATED, payload);
|
||||||
Payload::Text(values) => {
|
|
||||||
if let Some(first_value) = values.first() {
|
|
||||||
info!("Received friend-doll-updated event: {:?}", first_value);
|
|
||||||
} else {
|
|
||||||
info!("Received friend-doll-updated event with empty payload");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => error!("Received unexpected payload format for friend-doll-updated"),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_friend_doll_deleted(payload: Payload, _socket: RawClient) {
|
pub fn on_friend_doll_deleted(payload: Payload, _socket: RawClient) {
|
||||||
|
handle_friend_doll_change(WS_EVENT::FRIEND_DOLL_DELETED, payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_friend_doll_change(event_name: &str, payload: Payload) {
|
||||||
match payload {
|
match payload {
|
||||||
Payload::Text(values) => {
|
Payload::Text(values) => {
|
||||||
if let Some(first_value) = values.first() {
|
if let Some(first_value) = values.first() {
|
||||||
info!("Received friend-doll-deleted event: {:?}", first_value);
|
info!("Received {} event: {:?}", event_name, first_value);
|
||||||
|
// Future: Trigger re-fetch or emit to frontend
|
||||||
} else {
|
} else {
|
||||||
info!("Received friend-doll-deleted event with empty payload");
|
info!("Received {} event with empty payload", event_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => error!("Received unexpected payload format for friend-doll-deleted"),
|
_ => error!("Received unexpected payload format for {}", event_name),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
59
src-tauri/src/services/ws/handlers.rs
Normal file
59
src-tauri/src/services/ws/handlers.rs
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
use rust_socketio::{ClientBuilder, Event};
|
||||||
|
|
||||||
|
use crate::services::ws::WS_EVENT;
|
||||||
|
|
||||||
|
pub fn register_event_handlers(builder: ClientBuilder) -> ClientBuilder {
|
||||||
|
builder
|
||||||
|
.on(
|
||||||
|
WS_EVENT::FRIEND_REQUEST_RECEIVED,
|
||||||
|
super::friend::on_friend_request_received,
|
||||||
|
)
|
||||||
|
.on(
|
||||||
|
WS_EVENT::FRIEND_REQUEST_ACCEPTED,
|
||||||
|
super::friend::on_friend_request_accepted,
|
||||||
|
)
|
||||||
|
.on(
|
||||||
|
WS_EVENT::FRIEND_REQUEST_DENIED,
|
||||||
|
super::friend::on_friend_request_denied,
|
||||||
|
)
|
||||||
|
.on(WS_EVENT::UNFRIENDED, super::friend::on_unfriended)
|
||||||
|
.on(
|
||||||
|
WS_EVENT::FRIEND_CURSOR_POSITION,
|
||||||
|
super::friend::on_friend_cursor_position,
|
||||||
|
)
|
||||||
|
.on(
|
||||||
|
WS_EVENT::FRIEND_DISCONNECTED,
|
||||||
|
super::friend::on_friend_disconnected,
|
||||||
|
)
|
||||||
|
.on(
|
||||||
|
WS_EVENT::FRIEND_DOLL_CREATED,
|
||||||
|
super::friend::on_friend_doll_created,
|
||||||
|
)
|
||||||
|
.on(
|
||||||
|
WS_EVENT::FRIEND_DOLL_UPDATED,
|
||||||
|
super::friend::on_friend_doll_updated,
|
||||||
|
)
|
||||||
|
.on(
|
||||||
|
WS_EVENT::FRIEND_DOLL_DELETED,
|
||||||
|
super::friend::on_friend_doll_deleted,
|
||||||
|
)
|
||||||
|
.on(
|
||||||
|
WS_EVENT::FRIEND_ACTIVE_DOLL_CHANGED,
|
||||||
|
super::friend::on_friend_active_doll_changed,
|
||||||
|
)
|
||||||
|
.on(WS_EVENT::DOLL_CREATED, super::doll::on_doll_created)
|
||||||
|
.on(WS_EVENT::DOLL_UPDATED, super::doll::on_doll_updated)
|
||||||
|
.on(WS_EVENT::DOLL_DELETED, super::doll::on_doll_deleted)
|
||||||
|
.on(WS_EVENT::INITIALIZED, super::connection::on_initialized)
|
||||||
|
.on(
|
||||||
|
WS_EVENT::INTERACTION_RECEIVED,
|
||||||
|
super::interaction::on_interaction_received,
|
||||||
|
)
|
||||||
|
.on(
|
||||||
|
WS_EVENT::INTERACTION_DELIVERY_FAILED,
|
||||||
|
super::interaction::on_interaction_delivery_failed,
|
||||||
|
)
|
||||||
|
// rust-socketio fires Event::Connect on initial connect AND reconnects
|
||||||
|
// so we resend initialization there instead of a dedicated reconnect event.
|
||||||
|
.on(Event::Connect, super::connection::on_connected)
|
||||||
|
}
|
||||||
@@ -40,9 +40,11 @@ impl WS_EVENT {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mod client;
|
mod client;
|
||||||
|
mod connection;
|
||||||
mod cursor;
|
mod cursor;
|
||||||
mod doll;
|
mod doll;
|
||||||
mod friend;
|
mod friend;
|
||||||
|
mod handlers;
|
||||||
mod interaction;
|
mod interaction;
|
||||||
|
|
||||||
pub use client::init_ws_client;
|
pub use client::init_ws_client;
|
||||||
|
|||||||
Reference in New Issue
Block a user