2023-09-18 15:58:52 +08:00
|
|
|
package config
|
2023-09-18 15:51:20 +08:00
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"github.com/fsnotify/fsnotify"
|
|
|
|
"github.com/goccy/go-json"
|
|
|
|
"github.com/spf13/viper"
|
|
|
|
"go.uber.org/zap"
|
|
|
|
"path/filepath"
|
|
|
|
"sync"
|
|
|
|
)
|
|
|
|
|
|
|
|
type RWLock interface {
|
|
|
|
sync.Locker
|
|
|
|
RLock()
|
|
|
|
RUnlock()
|
|
|
|
}
|
|
|
|
|
|
|
|
type Config interface {
|
|
|
|
RWLock
|
|
|
|
}
|
|
|
|
|
|
|
|
func WriteConf(path string, conf any) (err error) {
|
|
|
|
var data []byte
|
|
|
|
data, err = json.Marshal(conf)
|
|
|
|
|
|
|
|
v := newViper(path)
|
|
|
|
if err = v.ReadConfig(bytes.NewBuffer(data)); err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
v.SetConfigType(filepath.Ext(path))
|
|
|
|
err = v.WriteConfig()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func ReadConf(path string, conf any) error {
|
|
|
|
return updateConfig(newViper(path), conf)
|
|
|
|
}
|
|
|
|
|
|
|
|
func ReadConfByKey(path, key string, conf any) error {
|
|
|
|
return updateConfigByKey(newViper(path), key, conf)
|
|
|
|
}
|
|
|
|
|
|
|
|
func ReadConfAndWatch(path string, conf Config, up func()) (err error) {
|
|
|
|
v := newViper(path)
|
|
|
|
|
|
|
|
if err = updateConfig(v, conf); err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
onUpdate := func(in fsnotify.Event) {
|
|
|
|
zap.L().Info("watch file", zap.Any("event", in))
|
|
|
|
if in.Name == "WRITE" {
|
|
|
|
conf.Lock()
|
|
|
|
defer conf.Unlock()
|
|
|
|
err = updateConfig(v, conf)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
zap.L().Error("auto update config err", zap.String("path", path), zap.Error(err))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if up != nil {
|
|
|
|
up()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// watch config WRITE event reread config
|
|
|
|
v.OnConfigChange(onUpdate)
|
|
|
|
v.WatchConfig()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func newViper(path string) (v *viper.Viper) {
|
|
|
|
v = viper.New()
|
|
|
|
v.SetConfigFile(path)
|
|
|
|
ext := filepath.Ext(path)
|
|
|
|
v.SetConfigType(ext[1:])
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func updateConfig(v *viper.Viper, conf any) (err error) {
|
|
|
|
if err = v.ReadInConfig(); err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
//zap.S().Info(v.AllSettings())
|
|
|
|
if err = v.Unmarshal(conf); err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
func updateConfigByKey(v *viper.Viper, key string, conf any) (err error) {
|
|
|
|
if err = v.ReadInConfig(); err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
//zap.S().Info(v.AllSettings())
|
|
|
|
if err = v.UnmarshalKey(key, conf); err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|