feat: HH-773 合集重命名接入 egress geo 缓存、geo 失败降级与每小时补探测
Build and Publish Docker Image / build-and-push (pull_request) Successful in 15m54s
Build and Publish Docker Image / build-and-push (pull_request) Successful in 15m54s
- service: EgressCacheKey 从 handler 下沉复用;MergeCachedEgressGeo 在合集 重命名前合并缓存 geo 字段(纯缓存读、零网络 I/O);StripEgressGeoFields 防止 geo 字段泄漏进订阅输出 - filter: geo 检测失败的节点保留 '[别名] 原名'(或纯原名)参与编号/排序, 不再丢弃 - handler: 每小时 StartEgressRefresher 对启用源补探测缺失/过期的 egress 缓存(含 TTL 内 error 结果一律跳过);RegisterRoutes 返回 *Deps; cmd/server.go 启动定时任务并在 shutdown 时取消 - tests: service 缓存 key 稳定性/合并/管道测试、handler 补探测跳过/TTL/ 过期/取消测试、filter 降级测试;修复 2 个过时测试(mihomo YAML 配置、 缓存命中路径)
This commit is contained in:
@@ -66,7 +66,8 @@ func geoFromNode(proxy model.ProxyNode) util.GeoInfo {
|
||||
// suffix) and numbered sequentially within each group, starting at 1.
|
||||
//
|
||||
// Nodes whose geographic info cannot be determined (no cached data and name
|
||||
// regex fails) are dropped from the output.
|
||||
// regex fails) are kept in the output under their original name (alias
|
||||
// prefixed), so they still participate in numbering and sorting.
|
||||
//
|
||||
// opts controls which fields are included in the output. A nil opts means all
|
||||
// fields are included (full default format).
|
||||
@@ -99,7 +100,19 @@ func RenameCollectionNodes(proxies []model.ProxyNode, opts *model.RenameOptions)
|
||||
geo = util.DetectGeo(ToString(proxy["name"]))
|
||||
}
|
||||
if geo.CountryName == "" {
|
||||
// Geo detection failed — skip this node
|
||||
// Geo detection failed — keep the node under its original name
|
||||
// (alias-prefixed) so it still participates in numbering and sorting.
|
||||
var parts []string
|
||||
if o.Alias && alias != "" {
|
||||
parts = append(parts, "["+alias+"]")
|
||||
}
|
||||
if name := ToString(proxy["name"]); name != "" {
|
||||
parts = append(parts, name)
|
||||
}
|
||||
infos = append(infos, nodeInfo{
|
||||
proxy: proxy,
|
||||
baseName: strings.Join(parts, " "),
|
||||
})
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
@@ -132,10 +132,21 @@ func TestRenameCollectionNodes_NoAlias(t *testing.T) {
|
||||
func TestRenameCollectionNodes_UnknownCountry(t *testing.T) {
|
||||
proxies := []model.ProxyNode{
|
||||
{"name": "Unknown Node", "type": "ss", "_sourceAlias": "A"},
|
||||
{"name": "Bare Node", "type": "ss"},
|
||||
}
|
||||
result := RenameCollectionNodes(proxies, nil)
|
||||
if len(result) != 0 {
|
||||
t.Fatalf("expected 0 nodes (no cached geo info, should be filtered), got %d", len(result))
|
||||
if len(result) != 2 {
|
||||
t.Fatalf("expected 2 nodes (geo-unknown nodes must be kept), got %d", len(result))
|
||||
}
|
||||
// Unknown geo: keep the original name, alias-prefixed when present
|
||||
if name, _ := result[0]["name"].(string); name != "[A] Unknown Node" {
|
||||
t.Errorf("node[0] name = %q, want %q", name, "[A] Unknown Node")
|
||||
}
|
||||
if name, _ := result[1]["name"].(string); name != "Bare Node" {
|
||||
t.Errorf("node[1] name = %q, want %q", name, "Bare Node")
|
||||
}
|
||||
if _, ok := result[0]["_sourceAlias"]; ok {
|
||||
t.Error("_sourceAlias should be stripped from rename output")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user