gitee.com/liuxuezhan/go-micro-v1.18.0@v1.0.0/config/default.go (about) 1 package config 2 3 import ( 4 "bytes" 5 "sync" 6 "time" 7 8 "gitee.com/liuxuezhan/go-micro-v1.18.0/config/loader" 9 "gitee.com/liuxuezhan/go-micro-v1.18.0/config/loader/memory" 10 "gitee.com/liuxuezhan/go-micro-v1.18.0/config/reader" 11 "gitee.com/liuxuezhan/go-micro-v1.18.0/config/reader/json" 12 "gitee.com/liuxuezhan/go-micro-v1.18.0/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 { 34 options := Options{ 35 Loader: memory.NewLoader(), 36 Reader: json.NewReader(), 37 } 38 39 for _, o := range opts { 40 o(&options) 41 } 42 43 options.Loader.Load(options.Source...) 44 snap, _ := options.Loader.Snapshot() 45 vals, _ := options.Reader.Values(snap.ChangeSet) 46 47 c := &config{ 48 exit: make(chan bool), 49 opts: options, 50 snap: snap, 51 vals: vals, 52 } 53 54 go c.run() 55 56 return c 57 } 58 59 func (c *config) run() { 60 watch := func(w loader.Watcher) error { 61 for { 62 // get changeset 63 snap, err := w.Next() 64 if err != nil { 65 return err 66 } 67 68 c.Lock() 69 70 // save 71 c.snap = snap 72 73 // set values 74 c.vals, _ = c.opts.Reader.Values(snap.ChangeSet) 75 76 c.Unlock() 77 } 78 } 79 80 for { 81 w, err := c.opts.Loader.Watch() 82 if err != nil { 83 time.Sleep(time.Second) 84 continue 85 } 86 87 done := make(chan bool) 88 89 // the stop watch func 90 go func() { 91 select { 92 case <-done: 93 case <-c.exit: 94 } 95 w.Stop() 96 }() 97 98 // block watch 99 if err := watch(w); err != nil { 100 // do something better 101 time.Sleep(time.Second) 102 } 103 104 // close done chan 105 close(done) 106 107 // if the config is closed exit 108 select { 109 case <-c.exit: 110 return 111 default: 112 } 113 } 114 } 115 116 func (c *config) Map() map[string]interface{} { 117 c.RLock() 118 defer c.RUnlock() 119 return c.vals.Map() 120 } 121 122 func (c *config) Scan(v interface{}) error { 123 c.RLock() 124 defer c.RUnlock() 125 return c.vals.Scan(v) 126 } 127 128 // sync loads all the sources, calls the parser and updates the config 129 func (c *config) Sync() error { 130 if err := c.opts.Loader.Sync(); err != nil { 131 return err 132 } 133 134 snap, err := c.opts.Loader.Snapshot() 135 if err != nil { 136 return err 137 } 138 139 c.Lock() 140 defer c.Unlock() 141 142 c.snap = snap 143 vals, err := c.opts.Reader.Values(snap.ChangeSet) 144 if err != nil { 145 return err 146 } 147 c.vals = vals 148 149 return nil 150 } 151 152 func (c *config) Close() error { 153 select { 154 case <-c.exit: 155 return nil 156 default: 157 close(c.exit) 158 } 159 return nil 160 } 161 162 func (c *config) Get(path ...string) reader.Value { 163 c.RLock() 164 defer c.RUnlock() 165 166 // did sync actually work? 167 if c.vals != nil { 168 return c.vals.Get(path...) 169 } 170 171 // no value 172 return newValue() 173 } 174 175 func (c *config) Bytes() []byte { 176 c.RLock() 177 defer c.RUnlock() 178 179 if c.vals == nil { 180 return []byte{} 181 } 182 183 return c.vals.Bytes() 184 } 185 186 func (c *config) Load(sources ...source.Source) error { 187 if err := c.opts.Loader.Load(sources...); err != nil { 188 return err 189 } 190 191 snap, err := c.opts.Loader.Snapshot() 192 if err != nil { 193 return err 194 } 195 196 c.Lock() 197 defer c.Unlock() 198 199 c.snap = snap 200 vals, err := c.opts.Reader.Values(snap.ChangeSet) 201 if err != nil { 202 return err 203 } 204 c.vals = vals 205 206 return nil 207 } 208 209 func (c *config) Watch(path ...string) (Watcher, error) { 210 value := c.Get(path...) 211 212 w, err := c.opts.Loader.Watch(path...) 213 if err != nil { 214 return nil, err 215 } 216 217 return &watcher{ 218 lw: w, 219 rd: c.opts.Reader, 220 path: path, 221 value: value, 222 }, nil 223 } 224 225 func (c *config) String() string { 226 return "config" 227 } 228 229 func (w *watcher) Next() (reader.Value, error) { 230 for { 231 s, err := w.lw.Next() 232 if err != nil { 233 return nil, err 234 } 235 236 // only process changes 237 if bytes.Equal(w.value.Bytes(), s.ChangeSet.Data) { 238 continue 239 } 240 241 v, err := w.rd.Values(s.ChangeSet) 242 if err != nil { 243 return nil, err 244 } 245 246 w.value = v.Get() 247 return w.value, nil 248 } 249 } 250 251 func (w *watcher) Stop() error { 252 return w.lw.Stop() 253 }