按审查结论重构:先补测试网,再搬代码
顺序是刻意的。前端一行测试都没有,直接挪代码挪坏了 bun test 不会红,所以先把纯逻辑 抽到能被测试的位置并补上用例,最后才动组件。测试从 37 条增加到 77 条。 抽出来的四块: - shared/outbound-chain.ts 「这个端口现在走哪条线」的链路解析,带防环,9 条测试 - web/delay-test.ts 延迟测试失败时说什么,6 个分支原本一条测试都没有 - web/runtime.ts 运行时状态的模块级单例,照 prefs.ts 已有的模式 - web/components/InboundList.vue 入站列表 出站的文本原本散成四份(读一份、显示一份、写回一份、表单又抄一份),加一种出站模式 要同时改四处,漏一个就是显示与写回不一致。合并成 OUTBOUND_PRESETS 一张表。 给认证和透传白名单补了 20 条测试。两者都是安全边界、都是纯函数、都不需要内核在线, 之前却只靠需要活内核的冒烟脚本间接覆盖。其中「形似但不是健康检查的路径」几条确认了 正则没写松。 另外:配置快照不再把整份文件原文下发(前端从不读,白白让响应体积翻倍); yaml-cosmetics 的测试改走生产路径,之前它自己拼了一遍三步流程,落盘链路漏掉其中一步 测试照样会绿。
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* 线路延迟测试。
|
||||
*
|
||||
* 单独成一个模块,是因为「测失败了该跟用户说什么」有六个分支,而它原本写在组件里,
|
||||
* 一条测试都加不了。这些话是用户唯一能看到的诊断信息,值得测。
|
||||
*/
|
||||
import { ref } from 'vue'
|
||||
import { ApiError, api } from './api'
|
||||
|
||||
/** 超时,毫秒。文案里会用到它,所以不能让接口和文案各写一个数。 */
|
||||
export const TEST_TIMEOUT_MS = 5000
|
||||
|
||||
/**
|
||||
* 把内核的延迟测试结果翻译成一句说明原因的话。
|
||||
*
|
||||
* 内核对这件事的回答是精确的(内核源码 hub/route/proxies.go:122-145):
|
||||
* 504 在给定超时内没有完成
|
||||
* 503 连接建立失败,或者测得的延迟为 0
|
||||
* 404 这个名字不在内核的全局出站表里
|
||||
* 笼统说一句「测不通」会把它们混在一起,而这三种要查的地方完全不一样。
|
||||
*/
|
||||
export function describeTestFailure(
|
||||
name: string,
|
||||
error: unknown,
|
||||
timeoutMs = TEST_TIMEOUT_MS,
|
||||
): string {
|
||||
if (!(error instanceof ApiError)) return `${name} 延迟测试失败:${String(error)}`
|
||||
|
||||
if (error.status === 504) {
|
||||
return `${name} 延迟测试超时,${String(timeoutMs / 1000)} 秒内没有取到测试地址`
|
||||
}
|
||||
|
||||
if (error.status === 404) {
|
||||
return `${name} 不在内核的出站表里,无法测试。订阅线路需要从所属订阅进去测。`
|
||||
}
|
||||
|
||||
const detail = String(error.payload.message ?? '')
|
||||
// 内核对连接失败给的是一句没有信息量的通用英文,替换成能指导排查的话
|
||||
const generic = detail === '' || detail === 'An error occurred in the delay test'
|
||||
|
||||
if (error.status === 503) {
|
||||
return generic
|
||||
? `${name} 无法建立连接,线路可能已失效,或本机到该服务器的网络不通`
|
||||
: `${name} 无法建立连接:${detail}`
|
||||
}
|
||||
|
||||
return `${name} 延迟测试失败(HTTP ${String(error.status)})${generic ? '' : `:${detail}`}`
|
||||
}
|
||||
|
||||
/**
|
||||
* 管理「哪几条线路正在测」。
|
||||
*
|
||||
* 测延迟是纯读操作,不影响配置也不影响别的线路,所以它只标记自己那一条忙碌,
|
||||
* 不禁用界面上的任何其它东西。
|
||||
*/
|
||||
export function useDelayTest(onFinished: () => void, onFailure: (message: string) => void) {
|
||||
const testing = ref<string[]>([])
|
||||
|
||||
async function test(name: string, provider?: string) {
|
||||
if (testing.value.includes(name)) return
|
||||
testing.value = [...testing.value, name]
|
||||
try {
|
||||
await api.testLine(name, provider, TEST_TIMEOUT_MS)
|
||||
onFinished()
|
||||
} catch (error) {
|
||||
// 测不通是关于线路的结论,不是 Patchbay 出了故障
|
||||
onFailure(describeTestFailure(name, error))
|
||||
} finally {
|
||||
testing.value = testing.value.filter((n) => n !== name)
|
||||
}
|
||||
}
|
||||
|
||||
return { testing, test }
|
||||
}
|
||||
Reference in New Issue
Block a user