github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/app/config/local.go (about) 1 package config 2 3 import ( 4 "encoding/json" 5 "os" 6 "path/filepath" 7 8 "github.com/fibonacci-chain/fbc/libs/tendermint/libs/log" 9 "github.com/fsnotify/fsnotify" 10 ) 11 12 const ( 13 LocalDynamicConfigPath = "config.dynamic.json" 14 ) 15 16 type LocalClient struct { 17 path string 18 dir string 19 fecConf *FecConfig 20 logger log.Logger 21 watcher *fsnotify.Watcher 22 close chan struct{} 23 } 24 25 func NewLocalClient(path string, oecConf *FecConfig, logger log.Logger) (*LocalClient, error) { 26 if logger == nil { 27 logger = log.NewNopLogger() 28 } 29 dir := filepath.Dir(path) 30 watcher, err := fsnotify.NewWatcher() 31 if err != nil { 32 return nil, err 33 } 34 client := &LocalClient{ 35 path: path, 36 dir: dir, 37 fecConf: oecConf, 38 logger: logger, 39 watcher: watcher, 40 close: make(chan struct{}), 41 } 42 go func() { 43 for { 44 select { 45 case event, ok := <-watcher.Events: 46 if !ok { 47 return 48 } 49 // logger.Debug("local config event", "event", event) 50 if event.Name == client.path && (event.Has(fsnotify.Write) || event.Has(fsnotify.Create)) { 51 logger.Debug("local config changed", "path", path) 52 ok = client.LoadConfig() 53 if !ok { 54 logger.Debug("local config changed but failed to load") 55 } else { 56 logger.Debug("local config changed and loaded") 57 } 58 } 59 case err, ok := <-watcher.Errors: 60 if !ok { 61 return 62 } 63 logger.Error("local config watcher error", "err", err) 64 case <-client.close: 65 logger.Debug("local client closed") 66 return 67 } 68 } 69 }() 70 71 return client, nil 72 } 73 74 func (a *LocalClient) Close() error { 75 close(a.close) 76 return a.watcher.Close() 77 } 78 79 func (a *LocalClient) Enable() (err error) { 80 return a.watcher.Add(a.dir) 81 } 82 83 func (a *LocalClient) configExists() bool { 84 _, err := os.Stat(a.path) 85 return !os.IsNotExist(err) 86 } 87 88 func (a *LocalClient) LoadConfig() (loaded bool) { 89 var conf map[string]string 90 bz, err := os.ReadFile(a.path) 91 if err != nil { 92 a.logger.Error("failed to read local config", "path", a.path, "err", err) 93 return false 94 } 95 err = json.Unmarshal(bz, &conf) 96 if err != nil { 97 a.logger.Error("failed to unmarshal local config", "path", a.path, "err", err) 98 return false 99 } 100 loaded = true 101 for k, v := range conf { 102 a.fecConf.updateFromKVStr(k, v) 103 } 104 a.logger.Info(a.fecConf.format()) 105 return 106 }