gitee.com/liuxuezhan/go-micro-v1.18.0@v1.0.0/config/loader/memory/memory.go (about) 1 package memory 2 3 import ( 4 "bytes" 5 "container/list" 6 "errors" 7 "fmt" 8 "strings" 9 "sync" 10 "time" 11 12 "gitee.com/liuxuezhan/go-micro-v1.18.0/config/loader" 13 "gitee.com/liuxuezhan/go-micro-v1.18.0/config/reader" 14 "gitee.com/liuxuezhan/go-micro-v1.18.0/config/reader/json" 15 "gitee.com/liuxuezhan/go-micro-v1.18.0/config/source" 16 ) 17 18 type memory struct { 19 exit chan bool 20 opts loader.Options 21 22 sync.RWMutex 23 // the current snapshot 24 snap *loader.Snapshot 25 // the current values 26 vals reader.Values 27 // all the sets 28 sets []*source.ChangeSet 29 // all the sources 30 sources []source.Source 31 32 watchers *list.List 33 } 34 35 type watcher struct { 36 exit chan bool 37 path []string 38 value reader.Value 39 reader reader.Reader 40 updates chan reader.Value 41 } 42 43 func (m *memory) watch(idx int, s source.Source) { 44 m.Lock() 45 m.sets = append(m.sets, &source.ChangeSet{Source: s.String()}) 46 m.Unlock() 47 48 // watches a source for changes 49 watch := func(idx int, s source.Watcher) error { 50 for { 51 // get changeset 52 cs, err := s.Next() 53 if err != nil { 54 return err 55 } 56 57 m.Lock() 58 59 // save 60 m.sets[idx] = cs 61 62 // merge sets 63 set, err := m.opts.Reader.Merge(m.sets...) 64 if err != nil { 65 m.Unlock() 66 return err 67 } 68 69 // set values 70 m.vals, _ = m.opts.Reader.Values(set) 71 m.snap = &loader.Snapshot{ 72 ChangeSet: set, 73 Version: fmt.Sprintf("%d", time.Now().Unix()), 74 } 75 m.Unlock() 76 77 // send watch updates 78 m.update() 79 } 80 } 81 82 for { 83 // watch the source 84 w, err := s.Watch() 85 if err != nil { 86 time.Sleep(time.Second) 87 continue 88 } 89 90 done := make(chan bool) 91 92 // the stop watch func 93 go func() { 94 select { 95 case <-done: 96 case <-m.exit: 97 } 98 w.Stop() 99 }() 100 101 // block watch 102 if err := watch(idx, w); err != nil { 103 // do something better 104 time.Sleep(time.Second) 105 } 106 107 // close done chan 108 close(done) 109 110 // if the config is closed exit 111 select { 112 case <-m.exit: 113 return 114 default: 115 } 116 } 117 } 118 119 func (m *memory) loaded() bool { 120 var loaded bool 121 m.RLock() 122 if m.vals != nil { 123 loaded = true 124 } 125 m.RUnlock() 126 return loaded 127 } 128 129 // reload reads the sets and creates new values 130 func (m *memory) reload() error { 131 m.Lock() 132 133 // merge sets 134 set, err := m.opts.Reader.Merge(m.sets...) 135 if err != nil { 136 m.Unlock() 137 return err 138 } 139 140 // set values 141 m.vals, _ = m.opts.Reader.Values(set) 142 m.snap = &loader.Snapshot{ 143 ChangeSet: set, 144 Version: fmt.Sprintf("%d", time.Now().Unix()), 145 } 146 147 m.Unlock() 148 149 // update watchers 150 m.update() 151 152 return nil 153 } 154 155 func (m *memory) update() { 156 watchers := make([]*watcher, 0, m.watchers.Len()) 157 158 m.RLock() 159 for e := m.watchers.Front(); e != nil; e = e.Next() { 160 watchers = append(watchers, e.Value.(*watcher)) 161 } 162 m.RUnlock() 163 164 for _, w := range watchers { 165 select { 166 case w.updates <- m.vals.Get(w.path...): 167 default: 168 } 169 } 170 } 171 172 // Snapshot returns a snapshot of the current loaded config 173 func (m *memory) Snapshot() (*loader.Snapshot, error) { 174 if m.loaded() { 175 m.RLock() 176 snap := loader.Copy(m.snap) 177 m.RUnlock() 178 return snap, nil 179 } 180 181 // not loaded, sync 182 if err := m.Sync(); err != nil { 183 return nil, err 184 } 185 186 // make copy 187 m.RLock() 188 snap := loader.Copy(m.snap) 189 m.RUnlock() 190 191 return snap, nil 192 } 193 194 // Sync loads all the sources, calls the parser and updates the config 195 func (m *memory) Sync() error { 196 //nolint:prealloc 197 var sets []*source.ChangeSet 198 199 m.Lock() 200 201 // read the source 202 var gerr []string 203 204 for _, source := range m.sources { 205 ch, err := source.Read() 206 if err != nil { 207 gerr = append(gerr, err.Error()) 208 continue 209 } 210 sets = append(sets, ch) 211 } 212 213 // merge sets 214 set, err := m.opts.Reader.Merge(sets...) 215 if err != nil { 216 m.Unlock() 217 return err 218 } 219 220 // set values 221 vals, err := m.opts.Reader.Values(set) 222 if err != nil { 223 m.Unlock() 224 return err 225 } 226 m.vals = vals 227 m.snap = &loader.Snapshot{ 228 ChangeSet: set, 229 Version: fmt.Sprintf("%d", time.Now().Unix()), 230 } 231 232 m.Unlock() 233 234 // update watchers 235 m.update() 236 237 if len(gerr) > 0 { 238 return fmt.Errorf("source loading errors: %s", strings.Join(gerr, "\n")) 239 } 240 241 return nil 242 } 243 244 func (m *memory) Close() error { 245 select { 246 case <-m.exit: 247 return nil 248 default: 249 close(m.exit) 250 } 251 return nil 252 } 253 254 func (m *memory) Get(path ...string) (reader.Value, error) { 255 if !m.loaded() { 256 if err := m.Sync(); err != nil { 257 return nil, err 258 } 259 } 260 261 m.Lock() 262 defer m.Unlock() 263 264 // did sync actually work? 265 if m.vals != nil { 266 return m.vals.Get(path...), nil 267 } 268 269 // assuming vals is nil 270 // create new vals 271 272 ch := m.snap.ChangeSet 273 274 // we are truly screwed, trying to load in a hacked way 275 v, err := m.opts.Reader.Values(ch) 276 if err != nil { 277 return nil, err 278 } 279 280 // lets set it just because 281 m.vals = v 282 283 if m.vals != nil { 284 return m.vals.Get(path...), nil 285 } 286 287 // ok we're going hardcore now 288 return nil, errors.New("no values") 289 } 290 291 func (m *memory) Load(sources ...source.Source) error { 292 var gerrors []string 293 294 for _, source := range sources { 295 set, err := source.Read() 296 if err != nil { 297 gerrors = append(gerrors, 298 fmt.Sprintf("error loading source %s: %v", 299 source, 300 err)) 301 // continue processing 302 continue 303 } 304 m.Lock() 305 m.sources = append(m.sources, source) 306 m.sets = append(m.sets, set) 307 idx := len(m.sets) - 1 308 m.Unlock() 309 go m.watch(idx, source) 310 } 311 312 if err := m.reload(); err != nil { 313 gerrors = append(gerrors, err.Error()) 314 } 315 316 // Return errors 317 if len(gerrors) != 0 { 318 return errors.New(strings.Join(gerrors, "\n")) 319 } 320 return nil 321 } 322 323 func (m *memory) Watch(path ...string) (loader.Watcher, error) { 324 value, err := m.Get(path...) 325 if err != nil { 326 return nil, err 327 } 328 329 m.Lock() 330 331 w := &watcher{ 332 exit: make(chan bool), 333 path: path, 334 value: value, 335 reader: m.opts.Reader, 336 updates: make(chan reader.Value, 1), 337 } 338 339 e := m.watchers.PushBack(w) 340 341 m.Unlock() 342 343 go func() { 344 <-w.exit 345 m.Lock() 346 m.watchers.Remove(e) 347 m.Unlock() 348 }() 349 350 return w, nil 351 } 352 353 func (m *memory) String() string { 354 return "memory" 355 } 356 357 func (w *watcher) Next() (*loader.Snapshot, error) { 358 for { 359 select { 360 case <-w.exit: 361 return nil, errors.New("watcher stopped") 362 case v := <-w.updates: 363 if bytes.Equal(w.value.Bytes(), v.Bytes()) { 364 continue 365 } 366 w.value = v 367 368 cs := &source.ChangeSet{ 369 Data: v.Bytes(), 370 Format: w.reader.String(), 371 Source: "memory", 372 Timestamp: time.Now(), 373 } 374 cs.Sum() 375 376 return &loader.Snapshot{ 377 ChangeSet: cs, 378 Version: fmt.Sprintf("%d", time.Now().Unix()), 379 }, nil 380 } 381 } 382 } 383 384 func (w *watcher) Stop() error { 385 select { 386 case <-w.exit: 387 default: 388 close(w.exit) 389 } 390 return nil 391 } 392 393 func NewLoader(opts ...loader.Option) loader.Loader { 394 options := loader.Options{ 395 Reader: json.NewReader(), 396 } 397 398 for _, o := range opts { 399 o(&options) 400 } 401 402 m := &memory{ 403 exit: make(chan bool), 404 opts: options, 405 watchers: list.New(), 406 sources: options.Source, 407 } 408 409 for i, s := range options.Source { 410 go m.watch(i, s) 411 } 412 413 return m 414 }