fix: teleport should never show reconnect dialog

This commit is contained in:
Evan Carroll 2026-01-20 11:29:22 -06:00
parent 32e5e42462
commit bf3bd3dff5
5 changed files with 153 additions and 20 deletions

View file

@ -20,14 +20,11 @@ use uuid::Uuid;
use chattyness_db::{
models::{AvatarRenderData, ChannelMemberWithAvatar, EmotionState, User},
queries::{avatars, channel_members, loose_props, realms, scenes},
ws_messages::{ClientMessage, DisconnectReason, ServerMessage, WsConfig},
ws_messages::{close_codes, ClientMessage, DisconnectReason, ServerMessage, WsConfig},
};
use chattyness_error::AppError;
use chattyness_shared::WebSocketConfig;
/// Close code for scene change (custom code).
const SCENE_CHANGE_CLOSE_CODE: u16 = 4000;
use crate::auth::AuthUser;
/// Channel state for broadcasting updates.
@ -397,8 +394,13 @@ async fn handle_socket(
// Create recv timeout from config
let recv_timeout = Duration::from_secs(ws_config.recv_timeout_secs);
// Channel for sending close frame requests from recv_task to send_task
let (close_tx, mut close_rx) = mpsc::channel::<(u16, String)>(1);
// Spawn task to handle incoming messages from client
let close_tx_for_recv = close_tx.clone();
let recv_task = tokio::spawn(async move {
let close_tx = close_tx_for_recv;
let pool = pool_for_recv;
let ws_state = ws_state_for_recv;
let mut disconnect_reason = DisconnectReason::Graceful;
@ -817,7 +819,7 @@ async fn handle_socket(
Message::Close(close_frame) => {
// Check close code for scene change
if let Some(CloseFrame { code, .. }) = close_frame {
if code == SCENE_CHANGE_CLOSE_CODE {
if code == close_codes::SCENE_CHANGE {
disconnect_reason = DisconnectReason::SceneChange;
} else {
disconnect_reason = DisconnectReason::Graceful;
@ -843,6 +845,12 @@ async fn handle_socket(
Err(_) => {
// Timeout elapsed - connection likely lost
tracing::info!("[WS] Connection timeout for user {}", user_id);
// Send close frame with timeout code so client can attempt silent reconnection
let _ = close_tx
.send((close_codes::SERVER_TIMEOUT, "timeout".to_string()))
.await;
// Brief delay to allow close frame to be sent
tokio::time::sleep(Duration::from_millis(100)).await;
disconnect_reason = DisconnectReason::Timeout;
break;
}
@ -852,10 +860,21 @@ async fn handle_socket(
(recv_conn, disconnect_reason)
});
// Spawn task to forward broadcasts and direct messages to this client
// Spawn task to forward broadcasts, direct messages, and close frames to this client
let send_task = tokio::spawn(async move {
loop {
tokio::select! {
// Handle close frame requests (from timeout)
Some((code, reason)) = close_rx.recv() => {
#[cfg(debug_assertions)]
tracing::debug!("[WS->Client] Sending close frame: code={}, reason={}", code, reason);
let close_frame = CloseFrame {
code,
reason: reason.into(),
};
let _ = sender.send(Message::Close(Some(close_frame))).await;
break;
}
// Handle broadcast messages
Ok(msg) = rx.recv() => {
if let Ok(json) = serde_json::to_string(&msg) {