// Package emspara EMS 参数(PID / VID)字典:SQLite -> Redis。 // // 字典的生成与使用: // 1. 部署时由 updateCmd 从 EMS 头文件 vid_macro.h / pid_macro.h 生成 SQLite,拷贝到部署目录(cmd/deploy_emspara.sh); // 2. 进程启动时调用 Init,把 SQLite 整体加载到 Redis(主服务与 fwh-agent-mcp 都会加载,替换是原子的); // 3. 查询走 Redis(repositories.GetEmsparaVidInfo / GetEmsparaPidInfo);发现 Redis 中没有字典时自动重新加载。 package emspara import ( "fmt" "fwh-toolbox-server/domain" "fwh-toolbox-server/repositories" "os" "go.uber.org/zap" "gorm.io/driver/sqlite" "gorm.io/gorm" "gorm.io/gorm/logger" ) // DefaultDBPath 字典 SQLite 的默认位置(相对工作目录,即部署目录 /var/www/fwh-toolbox/server) const DefaultDBPath = "./emspara.db" // Init 启动时加载字典到 Redis,并注册“Redis 中没有字典时重新加载”的回调。 // 加载失败只记录日志,不影响进程启动:查询时会再次尝试。 func Init(dbPath string) { repositories.SetEmsparaLoader(func() error { return SyncRedis(dbPath) }) if err := SyncRedis(dbPath); err != nil { zap.L().Error("[emspara] 加载 EMS 参数字典到 Redis 失败", zap.String("db", dbPath), zap.Error(err)) return } zap.L().Info("[emspara] EMS 参数字典已加载到 Redis", zap.String("db", dbPath)) } // SyncRedis 全量同步 SQLite -> Redis func SyncRedis(dbPath string) error { // 文件不存在时 SQLite 会新建空库,先检查,给出明确的错误 if _, err := os.Stat(dbPath); err != nil { return fmt.Errorf("字典文件不可用(部署时由 cmd/deploy_emspara.sh 生成): %w", err) } // 只读打开,不建表、不写入 db, err := gorm.Open(sqlite.Open("file:"+dbPath+"?mode=ro"), &gorm.Config{Logger: logger.Discard}) if err != nil { return fmt.Errorf("failed to connect database: %w", err) } if sqlDB, err := db.DB(); err == nil { defer sqlDB.Close() } var vidMacros []domain.ParamsVidMacroModel if err := db.Find(&vidMacros).Error; err != nil { return err } var pidMacros []domain.ParamsPidMacroModel if err := db.Find(&pidMacros).Error; err != nil { return err } return repositories.UpdateEmspara(vidMacros, pidMacros) }