go-micro.dev/v5@v5.12.0/config/default.go (about) 1 package config 2 3 import ( 4 "bytes" 5 "fmt" 6 "go-micro.dev/v5/config/loader" 7 "go-micro.dev/v5/config/loader/memory" 8 "go-micro.dev/v5/config/reader" 9 "go-micro.dev/v5/config/reader/json" 10 "go-micro.dev/v5/config/source" 11 "sync" 12 "time" 13 ) 14 15 type config struct { 16 // the current values 17 vals reader.Values 18 exit chan bool 19 // the current snapshot 20 snap *loader.Snapshot 21 opts Options 22 23 sync.RWMutex 24 } 25 26 type watcher struct { 27 lw loader.Watcher 28 rd reader.Reader 29 value reader.Value 30 path []string 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 return &c, nil 44 } 45 46 func (c *config) Init(opts ...Option) error { 47 c.opts = Options{ 48 Reader: json.NewReader(), 49 } 50 c.exit = make(chan bool) 51 for _, o := range opts { 52 o(&c.opts) 53 } 54 55 // default loader uses the configured reader 56 if c.opts.Loader == nil { 57 loaderOpts := []loader.Option{memory.WithReader(c.opts.Reader)} 58 if c.opts.WithWatcherDisabled { 59 loaderOpts = append(loaderOpts, memory.WithWatcherDisabled()) 60 } 61 62 c.opts.Loader = memory.NewLoader(loaderOpts...) 63 } 64 65 err := c.opts.Loader.Load(c.opts.Source...) 66 if err != nil { 67 return err 68 } 69 70 c.snap, err = c.opts.Loader.Snapshot() 71 if err != nil { 72 return err 73 } 74 75 c.vals, err = c.opts.Reader.Values(c.snap.ChangeSet) 76 if err != nil { 77 return err 78 } 79 80 return nil 81 } 82 83 func (c *config) Options() Options { 84 return c.opts 85 } 86 87 func (c *config) run() { 88 watch := func(w loader.Watcher) error { 89 for { 90 // get changeset 91 snap, err := w.Next() 92 if err != nil { 93 return err 94 } 95 96 c.Lock() 97 98 if c.snap.Version >= snap.Version { 99 c.Unlock() 100 continue 101 } 102 103 // save 104 c.snap = snap 105 106 // set values 107 c.vals, _ = c.opts.Reader.Values(snap.ChangeSet) 108 109 c.Unlock() 110 } 111 } 112 113 for { 114 w, err := c.opts.Loader.Watch() 115 if err != nil { 116 time.Sleep(time.Second) 117 continue 118 } 119 120 done := make(chan bool) 121 122 // the stop watch func 123 go func() { 124 select { 125 case <-done: 126 case <-c.exit: 127 } 128 err := w.Stop() 129 fmt.Println(err) 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, error) { 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(), nil 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 c.Lock() 244 defer c.Unlock() 245 246 if err := c.opts.Loader.Load(sources...); err != nil { 247 return err 248 } 249 250 snap, err := c.opts.Loader.Snapshot() 251 if err != nil { 252 return err 253 } 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, err := c.Get(path...) 267 if err != nil { 268 return nil, err 269 } 270 271 w, err := c.opts.Loader.Watch(path...) 272 if err != nil { 273 return nil, err 274 } 275 276 return &watcher{ 277 lw: w, 278 rd: c.opts.Reader, 279 path: path, 280 value: value, 281 }, nil 282 } 283 284 func (c *config) String() string { 285 return "config" 286 } 287 288 func (w *watcher) Next() (reader.Value, error) { 289 for { 290 s, err := w.lw.Next() 291 if err != nil { 292 return nil, err 293 } 294 295 // only process changes 296 if bytes.Equal(w.value.Bytes(), s.ChangeSet.Data) { 297 continue 298 } 299 300 v, err := w.rd.Values(s.ChangeSet) 301 if err != nil { 302 return nil, err 303 } 304 305 return v.Get() 306 } 307 } 308 309 func (w *watcher) Stop() error { 310 return w.lw.Stop() 311 }