123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- package conf
- import (
- "encoding/json"
- "errors"
- "leafstalk/log"
- "reflect"
- "sync"
- "leafstalk/otherutils/deepcopy"
- )
- // EventFunc 动态配置事件回调函数类型定义
- type EventFunc func(key string, val interface{})
- // event 动态事件结构体
- type event struct {
- sync.Mutex
- config map[string]interface{} // 本地缓存配置。用于初始化和对比新配置中的差异项,当存在差异项时进行回调处理使用
- list map[string][]EventFunc // 所有事件的列表
- }
- var dynamicEvent *event // 动态事件实例
- // initDynamicEvent 初始化动态配置事件
- func initDynamicEvent(cfgCenter *ConfigCenterAgent, group string) (err error) {
- dynamicEvent = &event{
- list: make(map[string][]EventFunc),
- }
- // 初始化时先获取一次动态配置,将其保存到本地
- content, err := cfgCenter.GetConfig("dynamicConfig", group)
- if err != nil {
- return
- }
- if err = json.Unmarshal([]byte(content), &dynamicEvent.config); err != nil {
- log.Warnf("initDynamicEvent error %v", content)
- return
- }
- if dynamicEvent.config == nil {
- err = errors.New("exception in obtaining dynamic config, config is nil")
- return
- }
- // 开始监听动态配置变化
- return cfgCenter.ListenChanges("dynamicConfig", group, func(namespace, group, dataId, newContent string) {
- var newConfig map[string]interface{}
- if err = json.Unmarshal([]byte(newContent), &newConfig); err != nil {
- // 解析配置出错,打印错误日志并返回
- log.Errorf("error parsing dynamic config for listen, err:%+v, newContent:%v", err, newContent)
- return
- }
- log.Infof("initDynamicEvent content %v", newContent)
- keys := CompareMaps(dynamicEvent.config, newConfig)
- if len(keys) == 0 {
- return
- }
- dynamicEvent.Lock()
- defer dynamicEvent.Unlock()
- dynamicEvent.config = newConfig
- for _, key := range keys {
- dynamicEvent.CallBack(key)
- }
- })
- }
- // CallBack 触发一个分组的事件回调
- func (e *event) CallBack(key string) {
- val := e.config[key]
- if cbfs, ok := e.list[key]; ok {
- for _, f := range cbfs {
- val2, err := deepcopy.Copy(val)
- if err != nil {
- log.Errorf("CallBack deepcopy error %v", err)
- }
- f(key, val2)
- }
- }
- }
- // CompareMaps 检查old 和 new 中每个 key 的值是否相等,返回不相等的key列表
- func CompareMaps(old, new map[string]interface{}) (diffKeys []string) {
- if new == nil {
- return
- }
- for key := range old {
- value2, ok := new[key]
- if ok && !reflect.DeepEqual(old[key], value2) {
- diffKeys = append(diffKeys, key)
- }
- }
- for key := range new {
- if _, ok := old[key]; !ok {
- diffKeys = append(diffKeys, key)
- }
- }
- return diffKeys
- }
- // RegisterAndCall 往一个分组中注册事件并触发一次事件回调
- // 这里的 keyGroup 表示一个配置键,同一个键可以有多个回调方法注册。
- // 当键发生变化时,会触发该键下所有注册的回调事件。
- func RegisterAndCall(key string, callback EventFunc) {
- dynamicEvent.Lock()
- defer dynamicEvent.Unlock()
- val := dynamicEvent.config[key]
- val2, err := deepcopy.Copy(val)
- if err != nil {
- log.Fatalf("RegisterAndCall deepcopy error %v", err)
- }
- dynamicEvent.list[key] = append(dynamicEvent.list[key], callback)
- callback(key, val2)
- }
|