V1.4.8: 按现场日志复盘优化取址等待与远程日志(含 15 秒白等修复)
依据用户提供的 1.4.7 现场日志(21 行,5 次点歌全部成功)复盘出四点: 1. 【行为,最大】每次点歌白等 15 秒。 日志里每首歌前都有一条「JS-BRIDGE 15s 未就绪」,紧跟着「NATIVE-SONG 取址成功 用时=3xx~7xxms」—— 即取址本身只要 0.3~0.7 秒,但用户从按下点歌到开始下载要等 15.7 秒。 原因: 桥一旦不可用,SongApiClient 每次都仍等满 15 秒。 修复: KtvJsBridge 新增「已判定不可用」状态(markUnavailable/isUnavailable), 首次判定后后续点歌直接走原生通道;桥万一恢复(热更新重载成功)自动清除该状态。 2. 【日志去噪】持久状态只记一次。 原来「15s 未就绪」按每次点歌一条 WARN 输出,一天几百条且无新增信息。 现在只在状态首次变化时记一条 ERROR。 3. 【可定位】补上"为什么不可用"。 旧日志里没有任何 KtvApi 未导出/WebView 初始化失败的行,说明 init 回调根本没触发。 KtvJsBridge.init 增加 20 秒看门狗: onPageFinished 未回调时明确上报 「初始化超时:onPageFinished 未回调或 KtvApi 未导出」; init 异常与 KtvApi 未导出也统一收敛到 markUnavailable。 4. 【上下文完整】启动关键行不再有 undefined。 旧日志的 STORAGE 行 serverip/clientip/user/traceid 全是 undefined(记在设备上下文之前), 而且 AppPaths.storageFacts() 会真实建目录、写探针、读 /proc/mounts —— 却跑在主线程。 现在把 STORAGE 移入 reportDeviceBootInfo() 的后台线程、在 refreshLogDeviceContext() 与 MiliLog.awaitServerIp() 之后上报: 上下文完整且不再阻塞主线程。 5. 【新增状态样本】每 6 小时一条 HEALTH(版本/在线/可用空间/曲库是否存在及大小/根目录)。 日志此前只有事件没有状态样本,无法排查"随时间变化"的问题(空间变少、曲库丢失、长期离线)。 6. 【字段一致】「请求源=」不再为空: 走原生兜底时 JS 的 reportSongResult 不会触发, 现在 SongUrlResolver 记录 lastHost,SongApiClient.lastSongSourceHost() 依次回退。 AGENTS.md 增补「写日志的五条约定」(只记一次/上下文完整/不做重活/可自我定位/状态样本+事件)。 版本 1.4.7(27) 到 1.4.8(28);签名证书不变。ktv_api.js 未改动,KTV_BRIDGE_API 仍为 8。
This commit is contained in:
@@ -55,6 +55,11 @@ object SongApiClient {
|
||||
return resolveNatively(musicno, resolution, h265) ?: fetchFromDb(musicno)
|
||||
}
|
||||
val bridge = bridge ?: return resolveNatively(musicno, resolution, h265) ?: fetchFromDb(musicno)
|
||||
// 已判定本机 WebView 不可用 → 不再每次白等 15 秒,直接用原生通道。
|
||||
// (极米 H1S 实测:每次都等满 15 秒,远程日志里每首歌前都有一条「15s 未就绪」。)
|
||||
if (bridge.isUnavailable()) {
|
||||
return resolveNatively(musicno, resolution, h265) ?: fetchFromDb(musicno)
|
||||
}
|
||||
// 等待 JS 桥"当前"真正就绪。首次冷启动时隐藏 WebView 的初始化在低性能设备
|
||||
// (极米投影等)上可能超过 3 秒;桥热更新重载期间 isReady() 也会短暂为 false。
|
||||
// 这里放宽到 15 秒,避免第一首歌因撞上就绪窗口而回退到不可靠的 DB cloud_url。
|
||||
@@ -67,9 +72,10 @@ object SongApiClient {
|
||||
}
|
||||
if (!bridge.isReady()) {
|
||||
// ⚠️ 老盒子(WebView 不可用)会一直走到这里。以前直接回退 DB,结果就是
|
||||
// 「无法生成下载地址」且远程日志里连一条 JS 日志都没有。现在改走原生解析器。
|
||||
// 「无法生成下载地址」且远程日志里连一条 JS 日志都没有。现在改走原生解析器,
|
||||
// 并把"不可用"记成持久状态(只上报一次),后续点歌不再等这 15 秒。
|
||||
Log.w(TAG, "Bridge not ready after wait, native resolver")
|
||||
MiliLog.warn("JS-BRIDGE 15s 未就绪,改用原生取址通道")
|
||||
bridge.markUnavailable("15s 未就绪")
|
||||
return resolveNatively(musicno, resolution, h265) ?: fetchFromDb(musicno)
|
||||
}
|
||||
val result = AtomicReference<String?>()
|
||||
@@ -140,7 +146,8 @@ object SongApiClient {
|
||||
bridge?.resetApiSession()
|
||||
}
|
||||
|
||||
/** 最近一次点歌实际命中的歌曲源 host(由 JS 上报, 用于远程日志)。 */
|
||||
/** 最近一次取址命中的源:优先 JS 上报,其次原生兜底记录(供远程日志的「请求源=」)。 */
|
||||
@JvmStatic
|
||||
fun lastSongSourceHost(): String = bridge?.lastSongSourceHost.orEmpty()
|
||||
fun lastSongSourceHost(): String =
|
||||
bridge?.lastSongSourceHost?.takeIf { it.isNotEmpty() } ?: SongUrlResolver.lastHost
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user