gitee.com/sasukebo/go-micro/v4@v4.7.1/config/default.go (about) 1 package config 2 3 import ( 4 "bytes" 5 "sync" 6 "time" 7 8 "gitee.com/sasukebo/go-micro/v4/config/loader" 9 "gitee.com/sasukebo/go-micro/v4/config/loader/memory" 10 "gitee.com/sasukebo/go-micro/v4/config/reader" 11 "gitee.com/sasukebo/go-micro/v4/config/reader/json" 12 "gitee.com/sasukebo/go-micro/v4/config/source" 13 ) 14 15 type config struct { 16 exit chan bool 17 opts Options 18 19 sync.RWMutex 20 // the current snapshot 21 snap *loader.Snapshot 22 // the current values 23 vals reader.Values 24 } 25 26 type watcher struct { 27 lw loader.Watcher 28 rd reader.Reader 29 path []string 30 value reader.Value 31 } 32 33 func newConfig(opts ...Option) (Config, error) { 34 var c config 35 36 err := c.Init(opts...) 37 if err != nil { 38 return nil, err 39 } 40 if !c.opts.WithWatcherDisabled { 41 go c.run() 42 } 43 44 return &c, nil 45 } 46 47 func (c *config) Init(opts ...Option) error { 48 c.opts = Options{ 49 Reader: json.NewReader(), 50 } 51 c.exit = make(chan bool) 52 for _, o := range opts { 53 o(&c.opts) 54 } 55 56 // default loader uses the configured reader 57 if c.opts.Loader == nil { 58 loaderOpts := []loader.Option{memory.WithReader(c.opts.Reader)} 59 if c.opts.WithWatcherDisabled { 60 loaderOpts = append(loaderOpts, memory.WithWatcherDisabled()) 61 } 62 63 c.opts.Loader = memory.NewLoader(loaderOpts...) 64 } 65 66 err := c.opts.Loader.Load(c.opts.Source...) 67 if err != nil { 68 return err 69 } 70 71 c.snap, err = c.opts.Loader.Snapshot() 72 if err != nil { 73 return err 74 } 75 76 c.vals, err = c.opts.Reader.Values(c.snap.ChangeSet) 77 if err != nil { 78 return err 79 } 80 81 return nil 82 } 83 84 func (c *config) Options() Options { 85 return c.opts 86 } 87 88 func (c *config) run() { 89 watch := func(w loader.Watcher) error { 90 for { 91 // get changeset 92 snap, err := w.Next() 93 if err != nil { 94 return err 95 } 96 97 c.Lock() 98 99 if c.snap.Version >= snap.Version { 100 c.Unlock() 101 continue 102 } 103 104 // save 105 c.snap = snap 106 107 // set values 108 c.vals, _ = c.opts.Reader.Values(snap.ChangeSet) 109 110 c.Unlock() 111 } 112 } 113 114 for { 115 w, err := c.opts.Loader.Watch() 116 if err != nil { 117 time.Sleep(time.Second) 118 continue 119 } 120 121 done := make(chan bool) 122 123 // the stop watch func 124 go func() { 125 select { 126 case <-done: 127 case <-c.exit: 128 } 129 w.Stop() 130 }() 131 132 // block watch 133 if err := watch(w); err != nil { 134 // do something better 135 time.Sleep(time.Second) 136 } 137 138 // close done chan 139 close(done) 140 141 // if the config is closed exit 142 select { 143 case <-c.exit: 144 return 145 default: 146 } 147 } 148 } 149 150 func (c *config) Map() map[string]interface{} { 151 c.RLock() 152 defer c.RUnlock() 153 return c.vals.Map() 154 } 155 156 func (c *config) Scan(v interface{}) error { 157 c.RLock() 158 defer c.RUnlock() 159 return c.vals.Scan(v) 160 } 161 162 // sync loads all the sources, calls the parser and updates the config 163 func (c *config) Sync() error { 164 if err := c.opts.Loader.Sync(); err != nil { 165 return err 166 } 167 168 snap, err := c.opts.Loader.Snapshot() 169 if err != nil { 170 return err 171 } 172 173 c.Lock() 174 defer c.Unlock() 175 176 c.snap = snap 177 vals, err := c.opts.Reader.Values(snap.ChangeSet) 178 if err != nil { 179 return err 180 } 181 c.vals = vals 182 183 return nil 184 } 185 186 func (c *config) Close() error { 187 select { 188 case <-c.exit: 189 return nil 190 default: 191 close(c.exit) 192 } 193 return nil 194 } 195 196 func (c *config) Get(path ...string) reader.Value { 197 c.RLock() 198 defer c.RUnlock() 199 200 // did sync actually work? 201 if c.vals != nil { 202 return c.vals.Get(path...) 203 } 204 205 // no value 206 return newValue() 207 } 208 209 func (c *config) Set(val interface{}, path ...string) { 210 c.Lock() 211 defer c.Unlock() 212 213 if c.vals != nil { 214 c.vals.Set(val, path...) 215 } 216 217 return 218 } 219 220 func (c *config) Del(path ...string) { 221 c.Lock() 222 defer c.Unlock() 223 224 if c.vals != nil { 225 c.vals.Del(path...) 226 } 227 228 return 229 } 230 231 func (c *config) Bytes() []byte { 232 c.RLock() 233 defer c.RUnlock() 234 235 if c.vals == nil { 236 return []byte{} 237 } 238 239 return c.vals.Bytes() 240 } 241 242 func (c *config) Load(sources ...source.Source) error { 243 if err := c.opts.Loader.Load(sources...); err != nil { 244 return err 245 } 246 247 snap, err := c.opts.Loader.Snapshot() 248 if err != nil { 249 return err 250 } 251 252 c.Lock() 253 defer c.Unlock() 254 255 c.snap = snap 256 vals, err := c.opts.Reader.Values(snap.ChangeSet) 257 if err != nil { 258 return err 259 } 260 c.vals = vals 261 262 return nil 263 } 264 265 func (c *config) Watch(path ...string) (Watcher, error) { 266 value := c.Get(path...) 267 268 w, err := c.opts.Loader.Watch(path...) 269 if err != nil { 270 return nil, err 271 } 272 273 return &watcher{ 274 lw: w, 275 rd: c.opts.Reader, 276 path: path, 277 value: value, 278 }, nil 279 } 280 281 func (c *config) String() string { 282 return "config" 283 } 284 285 func (w *watcher) Next() (reader.Value, error) { 286 for { 287 s, err := w.lw.Next() 288 if err != nil { 289 return nil, err 290 } 291 292 // only process changes 293 if bytes.Equal(w.value.Bytes(), s.ChangeSet.Data) { 294 continue 295 } 296 297 v, err := w.rd.Values(s.ChangeSet) 298 if err != nil { 299 return nil, err 300 } 301 302 w.value = v.Get() 303 return w.value, nil 304 } 305 } 306 307 func (w *watcher) Stop() error { 308 return w.lw.Stop() 309 }