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  }