修复: DeepSeek 400 全量扫描 + 队列 per-conv 隔离
- openai_compat: 扫描所有 assistant 消息剥离 orphan tool_calls(原仅查末条) - queue 加 conversationId 字段,按会话精准 drain - regenerate/editMessage 只清本会话排队消息 - newConversation 保留旧会话排队消息 - AiError 只清出错会话的队列项
This commit is contained in:
@@ -94,6 +94,13 @@ pub trait TunnelClient: Send + Sync {
|
||||
/// 此窗口内若收到 error 帧或连接 Close,判定握手失败)
|
||||
const HANDSHAKE_PROBE: Duration = Duration::from_secs(3);
|
||||
|
||||
/// TCP/WS 建立连接(connect_async)超时上限。
|
||||
///
|
||||
/// 对齐 df-ai http.rs connect_timeout(15s):relay URL 不可达(TCP SYN 无响应)时
|
||||
/// connect_async 会挂 60-120s 才返系统 timeout,Tauri 单线程 tokio runtime 卡死。
|
||||
/// 包 `tokio::time::timeout` 在此窗口内未完成 → 返 TunnelError::Connect 显式错误。
|
||||
const CONNECT_TIMEOUT: Duration = Duration::from_secs(15);
|
||||
|
||||
/// 心跳间隔(应用层 Ping,补协议层 keepalive,防 NAT 连接表超时回收)
|
||||
const HEARTBEAT_INTERVAL: Duration = Duration::from_secs(25);
|
||||
|
||||
@@ -177,10 +184,18 @@ impl TunnelClient for WsTunnelClient {
|
||||
self.cleanup_conn().await;
|
||||
}
|
||||
|
||||
// 1. 建立 WS 连接
|
||||
let (ws_stream, _resp) = tokio_tungstenite::connect_async(url)
|
||||
.await
|
||||
.map_err(|e| TunnelError::Connect(format!("WS 连接失败 {url}: {e}")))?;
|
||||
// 1. 建立 WS 连接(包 CONNECT_TIMEOUT 防 relay 不可达时永久挂 — TCP SYN 无响应
|
||||
// 系统 timeout 60-120s 才返,Tauri 单线程 tokio runtime 会卡死。对齐 df-ai http.rs
|
||||
// connect_timeout(15s)。保留原错误映射语义:TunnelError::Connect(format!("WS 连接失败 ..."))
|
||||
let connect_fut = tokio_tungstenite::connect_async(url);
|
||||
let (ws_stream, _resp) = match tokio::time::timeout(CONNECT_TIMEOUT, connect_fut).await {
|
||||
Ok(res) => res.map_err(|e| TunnelError::Connect(format!("WS 连接失败 {url}: {e}")))?,
|
||||
Err(_) => {
|
||||
return Err(TunnelError::Connect(format!(
|
||||
"WS 连接超时(>{CONNECT_TIMEOUT:?} 无响应){url}"
|
||||
)));
|
||||
}
|
||||
};
|
||||
tracing::info!(%url, "WS 连接已建立,开始 Hello 握手");
|
||||
|
||||
let (mut sink, mut stream) = ws_stream.split();
|
||||
|
||||
Reference in New Issue
Block a user