You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

97 lines
3.8 KiB

package console
import (
"sort"
"strings"
"yunyan/comm"
"yunyan/lego/sys/log"
"yunyan/lego/sys/postgres"
)
// ============================ 作用域键一致性巡检(只读,只打日志) ============================
//
// 按应用隔离的配置(svc_config / 会议模板 …)用 app_name 当作用域键,而这个键有三个来源,
// 三者必须是同一个字符串,错一个就会「后台改半天不生效」或「后台整页空白」,且**不报任何错**:
//
// ① 业务部署 .env 的 ANALYZE_APP_NAME —— 运行时 comm.AppName(),决定客户端读哪一套;
// ② 应用注册表 app_registry.app_name —— 迁移/复制/后台下拉用它;
// ③ 应用注册表 app_registry.name —— 统计落库认它(console.stat 的 getAppByName 查的是 name)。
//
// 线上真实踩过:测试机 app_registry 是 (name=EAIMAR-TEST, app_name=EAIMAR),而部署的
// ANALYZE_APP_NAME=EAIMAR-TEST。于是配置全落在 'EAIMAR-TEST' 作用域(客户端读得到),
// 后台下拉给出的却是 'EAIMAR'(app_name||name)→ 选它看到的是空页面,在那里新建的服务
// 客户端一个都读不到。两边都不报错,只有对着库查才看得出来。
//
// 巡检不改数据(作用域键是运维决定的,自动改名可能把线上配置搬到没人读的地方),
// 只把对不上的地方点名打出来。
func checkScopeConsistency(apps []*AppRegistry) {
known := map[string]bool{} // 注册表认得的作用域键(app_name 与 name 都算)
declared := map[string]bool{} // 后台下拉会给出的键(前端取 app_name||name,与它一致)
for _, a := range apps {
if !a.Enabled {
continue
}
n, an := strings.TrimSpace(a.Name), strings.TrimSpace(a.AppName)
if n != "" {
known[n] = true
}
if an != "" {
known[an] = true
}
if an != "" && n != "" && an != n {
log.Warnf("console.scope: 应用注册表 id=%d 的 name(%q) 与 app_name(%q) 不同值——"+
"配置作用域、后台下拉、统计落库三者会各认一个,务必改成同值(见 comm/appscope.go)", a.Id, n, an)
}
if d := an; d != "" {
declared[d] = true
} else if n != "" {
declared[n] = true
}
}
if len(known) == 0 {
return
}
for _, table := range []string{comm.TableSvcConfig, comm.TableEchomeetTemplate} {
var scopes []string
if err := postgres.Table(table).Group("app_name").Pluck("app_name", &scopes).Error; err != nil {
log.Warnf("console.scope: 巡检 %s 的作用域键失败(跳过): %v", table, err)
continue
}
orphan := make([]string, 0)
for _, s := range scopes {
s = strings.TrimSpace(s)
if s == "" || known[s] {
continue
}
orphan = append(orphan, s)
}
if len(orphan) > 0 {
sort.Strings(orphan)
log.Warnf("console.scope: %s 里有配置挂在注册表不认识的作用域 %v ——"+
"若某个业务部署的 ANALYZE_APP_NAME 正是它,那套配置正在生效却在后台**看不到也改不了**;"+
"对齐办法是把 app_registry 的 name/app_name 都改成这个值(不要改业务部署的 .env,"+
"那会让客户端立刻读到另一套配置)", table, orphan)
}
// 反向:后台下拉会给出、但库里一行配置都没有的作用域——选中它就是空白页。
empty := make([]string, 0)
for d := range declared {
found := false
for _, s := range scopes {
if strings.TrimSpace(s) == d {
found = true
break
}
}
if !found {
empty = append(empty, d)
}
}
if len(empty) > 0 && len(orphan) > 0 {
sort.Strings(empty)
log.Warnf("console.scope: %s 里作用域 %v 一行都没有,而后台下拉正会给出它们——"+
"配合上面那条孤儿作用域看,多半是同一个应用的两个名字", table, empty)
}
}
}