重构: 巨函数拆分 + 清理历史标记注释 + custom_prompt/停止按钮/tunnel 改进
This commit is contained in:
+36
-18
@@ -292,20 +292,14 @@ pub fn run() {
|
||||
Err(e) => tracing::warn!("[tunnel] 连接 relay 失败(非阻断,supervisor 将重试): {}", e),
|
||||
}
|
||||
|
||||
// ── supervisor:断线自动重连(根治 device 离线) ──
|
||||
// df-tunnel 无内置 auto-reconnect(tunnel.rs:332 注释留外层 supervisor)。
|
||||
// 桌面端进程重启 / 网络断 / relay 重启 → device 离线 → miniapp 命令 delivered=0
|
||||
// → 点发无响应。supervisor 轮询 is_connected,断开则用保存参数指数退避重连,
|
||||
// 复用同一 on_command 回调(逻辑不变)。task 永驻(supervisor 生命周期 = 应用生命周期)。
|
||||
// supervisor:轮询 is_connected,断开则重连
|
||||
// 连接被拒(relay 未部署)→300s+INFO;其他错误→2s-60s WARN
|
||||
let mut backoff = std::time::Duration::from_secs(2);
|
||||
let mut last_was_refused = false;
|
||||
loop {
|
||||
tokio::time::sleep(std::time::Duration::from_secs(5)).await;
|
||||
if !state.tunnel.is_connected() {
|
||||
tracing::info!(
|
||||
"[tunnel-supervisor] 检测到断开,尝试重连 url={} device_id={}",
|
||||
relay_url,
|
||||
device_id
|
||||
);
|
||||
tracing::info!("[tunnel-supervisor] 断线重连 url={relay_url} device_id={device_id}");
|
||||
match state
|
||||
.tunnel
|
||||
.connect(&relay_url, &device_id, &token, on_command.clone())
|
||||
@@ -314,24 +308,39 @@ pub fn run() {
|
||||
Ok(()) => {
|
||||
tracing::info!("[tunnel-supervisor] 重连成功,退避重置");
|
||||
backoff = std::time::Duration::from_secs(2);
|
||||
last_was_refused = false;
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::warn!(
|
||||
error = %e,
|
||||
backoff_secs = backoff.as_secs(),
|
||||
"[tunnel-supervisor] 重连失败,退避后重试"
|
||||
);
|
||||
tokio::time::sleep(backoff).await;
|
||||
// 指数退避上限 60s,防网络长故障时高频重连打 relay
|
||||
backoff = (backoff * 2).min(std::time::Duration::from_secs(60));
|
||||
let refused = is_connection_refused(&e);
|
||||
if refused {
|
||||
// relay 未运行:INFO + 300s 退避,不刷 WARN
|
||||
if !last_was_refused {
|
||||
tracing::info!("[tunnel-supervisor] relay 未运行({e}),300s 后轻量探测");
|
||||
last_was_refused = true;
|
||||
}
|
||||
// 300s 退避(避免空转刷屏,relay 未运行时一直保持此间隔)
|
||||
tokio::time::sleep(std::time::Duration::from_secs(300)).await;
|
||||
} else {
|
||||
tracing::warn!("[tunnel-supervisor] 重连失败 {e},退避 {backoff_secs}s", backoff_secs = backoff.as_secs());
|
||||
tokio::time::sleep(backoff).await;
|
||||
// 指数退避上限 60s,防网络长故障时高频重连打 relay
|
||||
backoff = (backoff * 2).min(std::time::Duration::from_secs(60));
|
||||
last_was_refused = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if last_was_refused {
|
||||
last_was_refused = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Ok(())
|
||||
})
|
||||
// 辅助函数 is_connection_refused 在文件尾部
|
||||
// 判断 TunnelError 是否为连接被拒(relay 未运行)。
|
||||
// 匹配 WS connect_async 产生的 IO error:ECONNREFUSED(Win:10061,Unix:111)。
|
||||
// 被拒 → relay 未部署,用长退避避免刷屏;其他错误(超时/DNS/网络瞬断)走指数退避。
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
// 项目
|
||||
commands::project::list_projects,
|
||||
@@ -500,3 +509,12 @@ pub fn run() {
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
}
|
||||
|
||||
/// 判断 TunnelError 是否为连接被拒(匹配 ECONNREFUSED 各平台表述)
|
||||
fn is_connection_refused(e: &df_tunnel::TunnelError) -> bool {
|
||||
let msg = e.to_string().to_lowercase();
|
||||
msg.contains("refused")
|
||||
|| msg.contains("10061")
|
||||
|| msg.contains("积极拒绝")
|
||||
|| msg.contains("actively refused")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user