diff --git a/core/loader.go b/core/loader.go index 0bab5b7..9c16c29 100644 --- a/core/loader.go +++ b/core/loader.go @@ -1,14 +1,16 @@ package core import ( - "encoding/json" "io" - "io/ioutil" - "path" + "strings" "mongo.games.com/goserver/core/logger" + "mongo.games.com/goserver/core/viperx" ) +var packages = make(map[string]Package) +var packagesLoaded = make(map[string]bool) + // Package 功能包 // 只做初始化,不要依赖其它功能包 type Package interface { @@ -16,84 +18,83 @@ type Package interface { Init() error io.Closer } -type ConfigFileEncryptorHook interface { - IsCipherText([]byte) bool - Encrypt([]byte) []byte - Decrtypt([]byte) []byte -} - -var packages = make(map[string]Package) -var packagesLoaded = make(map[string]bool) -var configFileEH ConfigFileEncryptorHook +// RegistePackage 注册功能包 func RegistePackage(p Package) { packages[p.Name()] = p } -func IsPackageRegisted(name string) bool { +// IsPackageRegistered 判断功能包是否已经注册 +func IsPackageRegistered(name string) bool { if _, exist := packages[name]; exist { return true } return false } +// IsPackageLoaded 判断功能包是否已经加载 func IsPackageLoaded(name string) bool { if _, exist := packagesLoaded[name]; exist { return true } return false } -func RegisterConfigEncryptor(h ConfigFileEncryptorHook) { - configFileEH = h + +// RegisterConfigEncryptor 注册配置文件加密器 +func RegisterConfigEncryptor(h viperx.ConfigFileEncryptorHook) { + viperx.RegisterConfigEncryptor(h) } + +// LoadPackages 加载功能包 func LoadPackages(configFile string) { - //logger.Logger.Infof("Build time is: %s", BuildTime()) - switch path.Ext(configFile) { - case ".json": - fileBuff, err := ioutil.ReadFile(configFile) - if err != nil { - logger.Logger.Errorf("Error while reading config file %s: %s", configFile, err) - break + val := strings.Split(configFile, ".") + if len(val) != 2 { + panic("config file name error") + } + + vp := viperx.GetViper(val[0], val[1]) + + var err error + var notFoundConfig []string + var notFoundPackage []string + for k := range vp.AllSettings() { + if _, ok := packages[k]; !ok { + notFoundPackage = append(notFoundPackage, k) + continue } - if configFileEH != nil { - if configFileEH.IsCipherText(fileBuff) { - fileBuff = configFileEH.Decrtypt(fileBuff) - } + + name := k + pkg := packages[k] + if err = vp.UnmarshalKey(k, pkg); err != nil { + logger.Logger.Errorf("Package %s: Error while unmarshalling from config file %s: %v", name, configFile, err) + continue } - var fileData interface{} - err = json.Unmarshal(fileBuff, &fileData) - if err != nil { - break + + if err = pkg.Init(); err != nil { + logger.Logger.Errorf("Package %s: Error while initializing from config file %s: %v", name, configFile, err) + continue } - fileMap := fileData.(map[string]interface{}) - for name, pkg := range packages { - if moduleData, ok := fileMap[name]; ok { - if data, ok := moduleData.(map[string]interface{}); ok { - modelBuff, _ := json.Marshal(data) - err = json.Unmarshal(modelBuff, &pkg) - if err != nil { - logger.Logger.Errorf("Error while unmarshalling JSON from config file %s: %s", configFile, err) - } else { - err = pkg.Init() - if err != nil { - logger.Logger.Errorf("Error while initializing package %s: %s", pkg.Name(), err) - } else { - packagesLoaded[pkg.Name()] = true - logger.Logger.Infof("package [%16s] load success", pkg.Name()) - } - } - } else { - logger.Logger.Errorf("Package %v init data unmarshal failed.", pkg.Name()) - } - } else { - logger.Logger.Errorf("Package %v init data not exist.", pkg.Name()) - } + + packagesLoaded[pkg.Name()] = true + logger.Logger.Infof("package [%16s] load success", pkg.Name()) + } + + for k := range packages { + if !IsPackageLoaded(k) { + notFoundConfig = append(notFoundConfig, k) } - default: - panic("Unsupported config file: " + configFile) + } + + if len(notFoundConfig) > 0 { + logger.Logger.Warnf("package load success, not found config: %v", notFoundConfig) + } + + if len(notFoundPackage) > 0 { + logger.Logger.Warnf("package load success, not found package: %v", notFoundPackage) } } +// ClosePackages 关闭功能包 func ClosePackages() { for _, pkg := range packages { err := pkg.Close() diff --git a/core/viperx/viper.go b/core/viperx/viper.go index 73519eb..59ff759 100644 --- a/core/viperx/viper.go +++ b/core/viperx/viper.go @@ -1,7 +1,9 @@ package viperx import ( + "bytes" "fmt" + "os" "github.com/spf13/viper" ) @@ -12,18 +14,50 @@ var paths = []string{ "./config", } +// ConfigFileEncryptorHook 配置文件加密器 +type ConfigFileEncryptorHook interface { + IsCipherText([]byte) bool + Encrypt([]byte) []byte + Decrypt([]byte) []byte +} + +var configFileEH ConfigFileEncryptorHook + +// RegisterConfigEncryptor 注册配置文件加密器 +func RegisterConfigEncryptor(h ConfigFileEncryptorHook) { + configFileEH = h +} + +// GetViper 获取viper配置 +// name: 配置文件名,不带后缀 +// filetype: 配置文件类型,如json、yaml、ini等 func GetViper(name, filetype string) *viper.Viper { - vp := viper.New() - // 配置文件 - vp.SetConfigName(name) - vp.SetConfigType(filetype) - for _, v := range paths { - vp.AddConfigPath(v) + buf, err := ReadFile(name, filetype) + if err != nil { + panic(fmt.Sprintf("Error while reading config file %s: %v", name+filetype, err)) } - err := vp.ReadInConfig() - if err != nil { - panic(fmt.Errorf("fatal error config file: %w", err)) + if configFileEH != nil { + if configFileEH.IsCipherText(buf) { + buf = configFileEH.Decrypt(buf) + } + } + + vp := viper.New() + vp.SetConfigName(name) + vp.SetConfigType(filetype) + if err = vp.ReadConfig(bytes.NewReader(buf)); err != nil { + panic(fmt.Sprintf("Error while reading config file %s: %v", name+filetype, err)) } return vp } + +func ReadFile(name, filetype string) ([]byte, error) { + for _, v := range paths { + file := fmt.Sprintf("%s/%s.%s", v, name, filetype) + if _, err := os.Stat(file); err == nil { + return os.ReadFile(file) + } + } + return nil, nil +}