center-config/manager/storage.go

253 lines
6.8 KiB
Go

// 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/gopkg/easylock"
"git.zhangdeman.cn/zhangdeman/gopkg/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)
}