pkg/config/config.go
2023-09-18 15:51:20 +08:00

104 lines
1.9 KiB
Go

package pkg
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
}