// Package manager... // // Description : 内存的数据存储 // // Author : go_developer@163.com<白茶清欢> // // Date : 2021-08-10 9:47 下午 package manager import ( "errors" "fmt" "sync" "time" "git.zhangdeman.cn/zhangdeman/center-config/define/model" "git.zhangdeman.cn/zhangdeman/easylock" "git.zhangdeman.cn/zhangdeman/easymap" ) type storage struct { // 数据锁 lock easylock.EasyLock // 命名空间表, 唯一标识 namespace 做key namespaceTable easymap.EasyMap // 命名空间表, 主键 ID 做key namespaceIDTable easymap.EasyMap // 主键 ID 和命名空间的映射关系 namespaceIDToNameTable easymap.EasyMap // 命名空间下有哪些配置项 namespaceConfigKeyTable easymap.EasyMap // 全局的配置项 configTable easymap.EasyMap } // InitNamespace 预加载命名空间 // // Author : go_developer@163.com<白茶清欢> // // Date : 9:48 下午 2021/8/10 func (s *storage) InitNamespace() error { var ( namespaceList []*model.Namespace err error ) if namespaceList, err = Namespace.GetAllNamespaceByStatus(model.NamespaceStatusNormal); nil != err { return err } // 存入内存 for _, item := range namespaceList { s.CreateNamespace(item) } return nil } // InitConfig 预加载配置 // // Author : go_developer@163.com<白茶清欢> // // Date : 9:49 下午 2021/8/10 func (s *storage) InitConfig() error { var ( allConfigList []*model.Config err error ) if allConfigList, err = Config.GetAllConfig(); nil != err { return err } // 按照namespace进行分组 groupConfig := make(map[int64][]string) // 存入内存 for _, conf := range allConfigList { if _, exist := groupConfig[conf.NamespaceID]; !exist { groupConfig[conf.NamespaceID] = make([]string, 0) } namespaceName, _ := s.namespaceIDToNameTable.GetString(conf.NamespaceID) configKey := s.CreateConfig(namespaceName, conf.Field, conf.Value) groupConfig[conf.NamespaceID] = append(groupConfig[conf.NamespaceID], configKey) } // 维护内存中命名空间配置项集合 for namespaceID, keyList := range groupConfig { s.namespaceConfigKeyTable.Set(namespaceID, keyList) } return nil } // CreateNamespace 创建内存的命名空间 // // Author : go_developer@163.com<白茶清欢> // // Date : 12:23 上午 2021/8/11 func (s *storage) CreateNamespace(namespaceInfo *model.Namespace) { s.namespaceTable.Set(namespaceInfo.Namespace, namespaceInfo) s.namespaceIDTable.Set(namespaceInfo.ID, namespaceInfo) s.namespaceIDToNameTable.Set(namespaceInfo.ID, namespaceInfo.Namespace) } // GetNamespace 获取命名空间信息 // // Author : go_developer@163.com<白茶清欢> // // Date : 2:16 下午 2021/11/30 func (s *storage) GetNamespace(np string) (*model.Namespace, error) { var ( result interface{} err error ) if result, err = s.namespaceTable.Get(np); nil != err { return nil, err } v, ok := result.(*model.Namespace) if !ok { return nil, errors.New("namespace info parse error") } return v, nil } // CreateConfig 创建内存配置(已存在,自动更新) // // Author : go_developer@163.com<白茶清欢> // // Date : 12:48 上午 2021/8/11 func (s *storage) CreateConfig(namespaceName string, field string, value string) string { confKey := s.getConfigKey(namespaceName, field) s.configTable.Set(confKey, value) return confKey } // DeleteNamespace 删除内存的命名空间 // // Author : go_developer@163.com<白茶清欢> // // Date : 12:22 上午 2021/8/11 func (s *storage) DeleteNamespace(namespaceName string, namespaceID int64) { s.namespaceTable.Del(namespaceName) s.namespaceIDToNameTable.Del(namespaceID) s.namespaceIDTable.Del(namespaceID) // 查询命名空间的配置 var confKeyList []string _ = s.configTable.GetWithReceiver(namespaceID, &confKeyList) // 删除命名空间对应内存配置 for _, key := range confKeyList { s.configTable.Del(key) } } // UpdateConfig 更新内存配置 // // Author : go_developer@163.com<白茶清欢> // // Date : 12:29 上午 2021/8/11 func (s *storage) UpdateConfig(namespaceInfo *model.Namespace, wg *sync.WaitGroup) { if nil != wg { wg.Done() } // 查询命名空间的配置 var ( confKeyList []string configList []*model.Config err error ) // 当前内存数据表 _ = s.namespaceConfigKeyTable.GetWithReceiver(namespaceInfo.ID, &confKeyList) currentMemConfigTable := make(map[string]bool) for _, confKey := range confKeyList { currentMemConfigTable[confKey] = true } if configList, err = Config.GetNamespaceConfig(namespaceInfo.ID); nil != err { // 出了异常, 不处理内存数据 return } newConfKeyList := make([]string, 0) for _, item := range configList { confKey := s.CreateConfig(namespaceInfo.Namespace, item.Field, item.Value) newConfKeyList = append(newConfKeyList, confKey) delete(currentMemConfigTable, confKey) } // 执行完 currentMemConfigTable 还有数据, 说明是已被删除数据, 从内存移除 for confKey := range currentMemConfigTable { s.configTable.Del(confKey) } // 更新命名空间维护的confKey s.namespaceConfigKeyTable.Set(namespaceInfo.ID, newConfKeyList) } // GetConf 读取内存配置 // // Author : go_developer@163.com<白茶清欢> // // Date : 1:09 上午 2021/8/11 func (s *storage) GetConf(namespaceName string, field string) string { confKey := s.getConfigKey(namespaceName, field) // 前置已经保证写入内存的一定是字符串 confValue, err := s.configTable.GetString(confKey) if nil != err { return "" } return confValue } // TimerUpdate 定时更新 // // Author : go_developer@163.com<白茶清欢> // // Date : 12:09 上午 2021/8/11 func (s *storage) TimerUpdate(timer int64) { if timer <= 0 { // 默认 10s 更新一次 timer = 10 } for { time.Sleep(time.Duration(timer) * time.Second) // 计时器到期 var ( namespaceList []*model.Namespace err error ) if namespaceList, err = Namespace.GetAllNamespaceByStatus(model.NamespaceStatusNormal); nil != err { break } namespaceTable := make(map[string]int64) for _, item := range namespaceList { namespaceTable[item.Namespace] = item.ID } // 当前内存数据 memData := s.namespaceIDToNameTable.GetAll() for namespaceID, namespaceName := range memData { if _, exist := namespaceTable[fmt.Sprintf("%v", namespaceID)]; !exist { // 更新后不存在, 删除 id, _ := namespaceID.(int64) name, _ := namespaceName.(string) s.DeleteNamespace(name, id) } } wg := &sync.WaitGroup{} wg.Add(len(namespaceList)) for _, namespaceInfo := range namespaceList { go s.UpdateConfig(namespaceInfo, wg) } } } // getConfigKey 获取内存配置key // // Author : go_developer@163.com<白茶清欢> // // Date : 1:08 上午 2021/8/11 func (s *storage) getConfigKey(namespaceName string, field string) string { return fmt.Sprintf("%v_%v", namespaceName, field) }