github.com/zly-app/zapp@v1.3.3/config/watch.key_object.go (about) 1 package config 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "strconv" 8 "sync" 9 "sync/atomic" 10 11 "go.uber.org/zap" 12 "gopkg.in/yaml.v3" 13 14 "github.com/zly-app/zapp/core" 15 "github.com/zly-app/zapp/logger" 16 ) 17 18 // 观察选项 19 type watchKeyObject struct { 20 p core.IConfigWatchProvider 21 opts *watchOptions 22 23 groupName string 24 keyName string 25 initOpts []core.ConfigWatchOption 26 27 callbacks []core.ConfigWatchKeyCallback 28 watchMx sync.Mutex // 用于锁 callback 29 30 data atomic.Value 31 initWG sync.WaitGroup 32 } 33 34 func (w *watchKeyObject) init() { 35 w.initWG.Add(1) 36 go func() { 37 waitAppInit() 38 w.opts = newWatchOptions(w.initOpts) 39 w.p = w.opts.Provider 40 41 // 立即获取 42 data, err := w.p.Get(w.groupName, w.keyName) 43 if err != nil { 44 logger.Log.Fatal("获取配置失败", 45 zap.String("groupName", w.groupName), 46 zap.String("keyName", w.keyName), 47 zap.Error(err)) 48 } 49 w.resetData(data) 50 51 // 开始观察 52 err = w.p.Watch(w.groupName, w.keyName, w.watchCallback) 53 if err != nil { 54 logger.Log.Fatal("watch配置失败", 55 zap.String("groupName", w.groupName), 56 zap.String("keyName", w.keyName), 57 zap.Error(err)) 58 } 59 60 w.initWG.Done() 61 }() 62 } 63 64 // 等待初始化 65 func (w *watchKeyObject) waitInit() { 66 w.initWG.Wait() 67 } 68 69 func (w *watchKeyObject) Opts() *watchOptions { 70 return w.opts 71 } 72 73 func (w *watchKeyObject) GroupName() string { return w.groupName } 74 func (w *watchKeyObject) KeyName() string { return w.keyName } 75 76 func (w *watchKeyObject) AddCallback(callback ...core.ConfigWatchKeyCallback) { 77 w.waitInit() 78 w.watchMx.Lock() 79 defer w.watchMx.Unlock() 80 81 items := make([]core.ConfigWatchKeyCallback, 0, len(callback)) 82 items = append(items, callback...) 83 w.callbacks = append(w.callbacks, items...) 84 85 // 立即触发 86 data := w.getRawData() 87 for _, fn := range callback { 88 fn(true, data, data) // 这里无法保证 data 被 callback 函数修改数据 89 } 90 } 91 92 func (w *watchKeyObject) GetData() []byte { 93 w.waitInit() 94 return w.getRawData() 95 } 96 97 // 检查是否复合预期的值 98 func (w *watchKeyObject) Expect(v interface{}) bool { 99 w.waitInit() 100 switch t := v.(type) { 101 case []byte: 102 return bytes.Equal(t, w.getRawData()) 103 case string: 104 return bytes.Equal([]byte(t), w.getRawData()) 105 case []rune: 106 return bytes.Equal([]byte(string(t)), w.getRawData()) 107 case bool: 108 temp, err := w.getBool() 109 if err != nil { 110 return false 111 } 112 return temp == t 113 case int: 114 return w.GetInt(t+1) == t 115 case int8: 116 return w.GetInt8(t+1) == t 117 case int16: 118 return w.GetInt16(t+1) == t 119 case int32: 120 return w.GetInt32(t+1) == t 121 case int64: 122 return w.GetInt64(t+1) == t 123 case uint: 124 return w.GetUint(t+1) == t 125 case uint8: 126 return w.GetUint8(t+1) == t 127 case uint16: 128 return w.GetUint16(t+1) == t 129 case uint32: 130 return w.GetUint32(t+1) == t 131 case uint64: 132 return w.GetUint64(t+1) == t 133 case float32: 134 return w.GetFloat32(t+1) == t 135 case float64: 136 return w.GetFloat64(t+1) == t 137 } 138 return false 139 } 140 141 func (w *watchKeyObject) GetString() string { 142 w.waitInit() 143 return string(w.getRawData()) 144 } 145 func (w *watchKeyObject) getBool() (bool, error) { 146 switch v := w.GetString(); v { 147 case "1", "t", "T", "true", "TRUE", "True", "y", "Y", "yes", "YES", "Yes", 148 "on", "ON", "On", "ok", "OK", "Ok", 149 "enabled", "ENABLED", "Enabled", 150 "open", "OPEN", "Open": 151 return true, nil 152 case "0", "f", "F", "false", "FALSE", "False", "n", "N", "no", "NO", "No", 153 "off", "OFF", "Off", "cancel", "CANCEL", "Cancel", 154 "disable", "DISABLE", "Disable", 155 "close", "CLOSE", "Close": 156 return false, nil 157 default: 158 return false, fmt.Errorf("data %s can't conver to boolean", v) 159 } 160 } 161 func (w *watchKeyObject) GetBool(def ...bool) bool { 162 w.waitInit() 163 v, err := w.getBool() 164 if err == nil { 165 return v 166 } 167 if len(def) > 0 { 168 return def[0] 169 } 170 return false 171 } 172 func (w *watchKeyObject) GetInt(def ...int) int { 173 w.waitInit() 174 v, err := strconv.Atoi(w.GetString()) 175 if err == nil { 176 return v 177 } 178 if len(def) > 0 { 179 return def[0] 180 } 181 return 0 182 } 183 func (w *watchKeyObject) GetInt8(def ...int8) int8 { 184 w.waitInit() 185 v, err := strconv.ParseInt(w.GetString(), 10, 8) 186 if err == nil { 187 return int8(v) 188 } 189 if len(def) > 0 { 190 return def[0] 191 } 192 return 0 193 } 194 func (w *watchKeyObject) GetInt16(def ...int16) int16 { 195 w.waitInit() 196 v, err := strconv.ParseInt(w.GetString(), 10, 16) 197 if err == nil { 198 return int16(v) 199 } 200 if len(def) > 0 { 201 return def[0] 202 } 203 return 0 204 } 205 func (w *watchKeyObject) GetInt32(def ...int32) int32 { 206 w.waitInit() 207 v, err := strconv.ParseInt(w.GetString(), 10, 32) 208 if err == nil { 209 return int32(v) 210 } 211 if len(def) > 0 { 212 return def[0] 213 } 214 return 0 215 } 216 func (w *watchKeyObject) GetInt64(def ...int64) int64 { 217 w.waitInit() 218 v, err := strconv.ParseInt(w.GetString(), 10, 64) 219 if err == nil { 220 return v 221 } 222 if len(def) > 0 { 223 return def[0] 224 } 225 return 0 226 } 227 func (w *watchKeyObject) GetUint(def ...uint) uint { 228 w.waitInit() 229 v, err := strconv.ParseUint(w.GetString(), 10, 64) 230 if err == nil { 231 return uint(v) 232 } 233 if len(def) > 0 { 234 return def[0] 235 } 236 return 0 237 } 238 func (w *watchKeyObject) GetUint8(def ...uint8) uint8 { 239 w.waitInit() 240 v, err := strconv.ParseUint(w.GetString(), 10, 8) 241 if err == nil { 242 return uint8(v) 243 } 244 if len(def) > 0 { 245 return def[0] 246 } 247 return 0 248 } 249 func (w *watchKeyObject) GetUint16(def ...uint16) uint16 { 250 w.waitInit() 251 v, err := strconv.ParseUint(w.GetString(), 10, 16) 252 if err == nil { 253 return uint16(v) 254 } 255 if len(def) > 0 { 256 return def[0] 257 } 258 return 0 259 } 260 func (w *watchKeyObject) GetUint32(def ...uint32) uint32 { 261 w.waitInit() 262 v, err := strconv.ParseUint(w.GetString(), 10, 32) 263 if err == nil { 264 return uint32(v) 265 } 266 if len(def) > 0 { 267 return def[0] 268 } 269 return 0 270 } 271 func (w *watchKeyObject) GetUint64(def ...uint64) uint64 { 272 w.waitInit() 273 v, err := strconv.ParseUint(w.GetString(), 10, 64) 274 if err == nil { 275 return v 276 } 277 if len(def) > 0 { 278 return def[0] 279 } 280 return 0 281 } 282 func (w *watchKeyObject) GetFloat32(def ...float32) float32 { 283 w.waitInit() 284 v, err := strconv.ParseFloat(w.GetString(), 32) 285 if err == nil { 286 return float32(v) 287 } 288 if len(def) > 0 { 289 return def[0] 290 } 291 return 0 292 } 293 func (w *watchKeyObject) GetFloat64(def ...float64) float64 { 294 w.waitInit() 295 v, err := strconv.ParseFloat(w.GetString(), 64) 296 if err == nil { 297 return v 298 } 299 if len(def) > 0 { 300 return def[0] 301 } 302 return 0 303 } 304 305 func (w *watchKeyObject) ParseJSON(outPtr interface{}) error { 306 w.waitInit() 307 return json.Unmarshal(w.getRawData(), outPtr) 308 } 309 func (w *watchKeyObject) ParseYaml(outPtr interface{}) error { 310 w.waitInit() 311 return yaml.Unmarshal(w.getRawData(), outPtr) 312 } 313 314 // 获取原始数据 315 func (w *watchKeyObject) getRawData() []byte { 316 data := w.data.Load().([]byte) 317 return data 318 } 319 320 // 回调 321 func (w *watchKeyObject) watchCallback(_, _ string, _, newData []byte) { 322 oldData := w.getRawData() 323 if bytes.Equal(newData, oldData) { 324 return 325 } 326 327 w.resetData(newData) 328 logger.Log.Info("配置数据变更", 329 zap.String("groupName", w.groupName), 330 zap.String("keyName", w.keyName), 331 zap.String("oldData", string(oldData)), 332 zap.String("newData", string(newData)), 333 ) 334 335 w.watchMx.Lock() 336 defer w.watchMx.Unlock() 337 for _, fn := range w.callbacks { 338 go fn(false, oldData, newData) // 这里无法保证 newData 被 callback 函数修改数据 339 } 340 } 341 342 // 重新设置数据 343 func (w *watchKeyObject) resetData(data []byte) { 344 if data == nil { 345 data = make([]byte, 0) 346 } 347 w.data.Store(data) 348 } 349 350 func newWatchKeyObject(groupName, keyName string, opts ...core.ConfigWatchOption) *watchKeyObject { 351 w := &watchKeyObject{ 352 groupName: groupName, 353 keyName: keyName, 354 initOpts: opts, 355 } 356 w.init() 357 return w 358 } 359 360 // 观察key, 失败会fatal 361 func WatchKey(groupName, keyName string, opts ...core.ConfigWatchOption) core.IConfigWatchKeyObject { 362 w := newWatchKeyObject(groupName, keyName, opts...) 363 return w 364 }