chore(client/macos): 清理延迟排查的诊断打点 + debug 注入(最终干净版)
延迟显示已修通。移除排查期的临时诊断:扩展侧 Log 客户端/klog 捕获、log.level=debug 注入、 diag 字段/setDiag;主 app StatsClient 每5帧的 dl/ul/urltest 打印;Dart 侧 [Stats]/[Ping] 打点。 保留全部修复:clash_api 注入取 urltest、sendProviderMessage 统计通道、/proxies history+active 缓存、共享广播流、_onStats 回退 effectiveNode、连接态跳过直连实测。 CURRENT_PROJECT_VERSION 52→53。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -81,7 +81,6 @@ class ConnectionController extends StateNotifier<ConnectionState> {
|
||||
_statusSub = _bridge.statusStream.listen(_onKernelStatus);
|
||||
// 订阅内核 stats:连接态把 urltest 实测回写连接节点的 ping,让连接页与节点列表同源一致。
|
||||
_statsSub = _bridge.statsStream.listen(_onStats);
|
||||
logLine('Stats', 'ConnectionController constructed, statsStream subscribed');
|
||||
// 登出(主动退出 / 被强制下线 / 会话过期)→ 一律断开隧道:别让已登出/被踢的设备继续用
|
||||
// 数据面。一处监听 auth 覆盖所有登出路径。token 续期(仍登录)不触发。
|
||||
_authSub = _ref.listen<AuthState>(authProvider, (prev, next) {
|
||||
@@ -245,24 +244,16 @@ class ConnectionController extends StateNotifier<ConnectionState> {
|
||||
// 连接态:取内核 urltest 最小正延迟,回写连接节点 ping。全局 TUN 下 App 直接探测节点不可行,
|
||||
// 内核(经 REALITY 真实直连数据面)是唯一能实测的;回写到 node.ping → 连接页/节点列表同源。
|
||||
void _onStats(VpnStatsEvent e) {
|
||||
// 无条件打点:确认 _onStats 是否被调用、当前 phase、urltest 是否到达 Dart 侧。
|
||||
logLine('Stats',
|
||||
'onStats phase=${state.phase.name} '
|
||||
'urltest=[${e.urltestResults.map((r) => "${r.tag}:${r.delayMs}").join(",")}]');
|
||||
if (state.phase != VpnPhase.on) return;
|
||||
// 自动连接/重连到已在跑的隧道时不会走 _connect → _connectedNode 为 null;回退到
|
||||
// effectiveNode(当前/智能所选),否则 urltest 实测无处回写、连接页延迟一直显示 —。
|
||||
final Node node = _connectedNode ?? _ref.read(effectiveNodeProvider);
|
||||
final ds = e.urltestResults.where((r) => r.delayMs > 0).map((r) => r.delayMs).toList();
|
||||
logLine('Stats',
|
||||
'conn=${_connectedNode == null ? "null" : _connectedNode!.code} '
|
||||
'eff=${node.code}/${node.uuid.isEmpty ? "EMPTY" : "ok"} ds=$ds');
|
||||
if (node.uuid.isEmpty) return;
|
||||
final ds = e.urltestResults.where((r) => r.delayMs > 0).map((r) => r.delayMs);
|
||||
if (ds.isEmpty) return;
|
||||
// urltest 成功:经 proxy 出站(REALITY 到节点)真实可达 → 记录时刻(供路径 A 判活)+ 回写延迟。
|
||||
_lastUrltestOk = DateTime.now();
|
||||
final best = ds.reduce((a, b) => a < b ? a : b);
|
||||
logLine('Stats', 'setLivePing node=${node.code} = ${best}ms');
|
||||
_ref.read(nodesProvider.notifier).setLivePing(node.uuid, best);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ import '../services/api_config.dart';
|
||||
import '../services/latency_probe.dart';
|
||||
import 'auth_provider.dart';
|
||||
import 'connection_provider.dart';
|
||||
import '../bridge/log.dart';
|
||||
|
||||
// ── 节点列表 AsyncNotifier ────────────────────────────────────────
|
||||
|
||||
@@ -87,24 +86,14 @@ class NodesNotifier extends AsyncNotifier<List<Node>> {
|
||||
/// 回写某节点的实测延迟(ms)。连接态由 ConnectionController 用内核 urltest 回填连接节点,
|
||||
/// 让「连接页延迟」与「节点列表延迟」同源(都读 node.ping)、显示一致。ms<=0 忽略。
|
||||
void setLivePing(String uuid, int ms) {
|
||||
if (ms <= 0 || _disposed) {
|
||||
logLine('Ping', 'setLivePing SKIP ms=$ms disposed=$_disposed');
|
||||
return;
|
||||
}
|
||||
if (ms <= 0 || _disposed) return;
|
||||
final list = state.valueOrNull;
|
||||
if (list == null) {
|
||||
logLine('Ping', 'setLivePing no-list');
|
||||
return;
|
||||
}
|
||||
if (list == null) return;
|
||||
var changed = false;
|
||||
final updated = [
|
||||
for (final n in list)
|
||||
if (n.uuid == uuid && n.ping != ms) (() { changed = true; return n.copyWith(ping: ms); })() else n
|
||||
];
|
||||
final match = list.any((n) => n.uuid == uuid);
|
||||
logLine('Ping',
|
||||
'setLivePing ms=$ms match=$match changed=$changed '
|
||||
'nodes=[${list.map((n) => "${n.code}:${n.ping}").join(",")}]');
|
||||
if (changed) state = AsyncData(updated);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user