Add registered map and implement the Local watch function.

This commit is contained in:
cyprinus 2023-03-23 00:40:14 +08:00
parent 3970ad177e
commit 4bb20e2c5a
3 changed files with 83 additions and 1 deletions

19
register.go Normal file
View file

@ -0,0 +1,19 @@
package viper
type RegisteredConfig struct {
Key string
CanBeNil bool
OnUpdate func(e *Event)
OnUpdateFailed func(e *Event)
Schema *interface{}
Validator func(interface{}) bool
}
func (v *Viper) Register(r []RegisteredConfig) {
if v.registered == nil {
v.registered = make(map[string]RegisteredConfig)
}
for _, config := range r {
v.registered[config.Key] = config
}
}

View file

@ -22,6 +22,7 @@ package viper
import (
"bytes"
"encoding/csv"
js "encoding/json"
"errors"
"fmt"
"io"
@ -223,6 +224,8 @@ type Viper struct {
// TODO: should probably be protected with a mutex
encoderRegistry *encoding.EncoderRegistry
decoderRegistry *encoding.DecoderRegistry
registered map[string]RegisteredConfig
}
// New returns an initialized Viper instance.
@ -474,10 +477,57 @@ func (v *Viper) WatchConfig() {
(event.Has(fsnotify.Write) || event.Has(fsnotify.Create))) ||
(currentConfigFile != "" && currentConfigFile != realConfigFile) {
realConfigFile = currentConfigFile
err := v.ReadInConfig()
tempViper := New()
tempViper.AddConfigPath(realConfigFile)
err := tempViper.ReadInConfig()
if err != nil {
log.Printf("error reading config file: %v\n", err)
}
for key, config := range v.registered {
oldValue := v.Get(key)
newValue := tempViper.Get(key)
// Check exist
if newValue == nil && !config.CanBeNil {
if config.OnUpdateFailed != nil {
config.OnUpdateFailed(&Event{
old: oldValue,
new: nil,
})
}
continue
}
// Type check & convert
newValueJson, _ := js.Marshal(newValue)
err = js.Unmarshal(newValueJson, config.Schema)
if err != nil {
config.OnUpdateFailed(&Event{
old: oldValue,
new: nil,
})
continue
}
// Validation
if !config.Validator(config.Schema) {
config.OnUpdateFailed(&Event{
old: oldValue,
new: nil,
})
continue
}
// Success
v.Set(key, config.Schema)
if config.OnUpdate != nil {
config.OnUpdate(&Event{
new: config.Schema,
old: oldValue,
})
}
}
if v.onConfigChange != nil {
v.onConfigChange(event)
}

View file

@ -10,3 +10,16 @@ type watcher = fsnotify.Watcher
func newWatcher() (*watcher, error) {
return fsnotify.NewWatcher()
}
type Event struct {
new interface{}
old interface{}
}
func (s *Event) New() interface{} {
return s.new
}
func (s *Event) Old() interface{} {
return s.old
}