package task import ( "dsbqj-admin/model/mongo/abver" "dsbqj-admin/model/mongo/md5" "strings" "sync" "github.com/kamva/mgm/v3" "go.mongodb.org/mongo-driver/bson" ) type VersionConfigCache struct { sync.RWMutex abVers map[string][]*abver.AbVer md5s map[string][]*md5.MD5 } type ConfigValue struct { Version string Value string } var VersionConfigTask = &VersionConfigCache{} func (cache *VersionConfigCache) Reload() { abVers := make([]*abver.AbVer, 0) md5s := make([]*md5.MD5, 0) if mgm.Coll(&abver.AbVer{}).SimpleFind(&abVers, bson.M{}) != nil || mgm.Coll(&md5.MD5{}).SimpleFind(&md5s, bson.M{}) != nil { return } newAbVers := make(map[string][]*abver.AbVer) for _, item := range abVers { key := configKey(item.Platform) newAbVers[key] = append(newAbVers[key], item) } newMD5s := make(map[string][]*md5.MD5) for _, item := range md5s { key := configKey(item.Platform) newMD5s[key] = append(newMD5s[key], item) } cache.Lock() cache.abVers, cache.md5s = newAbVers, newMD5s cache.Unlock() } func (cache *VersionConfigCache) RefreshAbVer(item *abver.AbVer) { cache.Reload() } func (cache *VersionConfigCache) RefreshMD5(item *md5.MD5) { cache.Reload() } func (cache *VersionConfigCache) GetAbVer(platform, env string) ConfigValue { cache.RLock() defer cache.RUnlock() if value, ok := highestAbVer(cache.abVers[configKey(platform)], env); ok { return value } if strings.TrimSpace(platform) != "" { value, _ := highestAbVer(cache.abVers[configKey("")], env) return value } return ConfigValue{} } func highestAbVer(items []*abver.AbVer, env string) (ConfigValue, bool) { var result *abver.AbVer for _, item := range items { if item.External && configEnvMatches(item.EnvVersions, env) && (result == nil || CompareConfigVersion(item.Version, result.Version) > 0) { result = item } } if result == nil { return ConfigValue{}, false } return ConfigValue{Version: result.Version, Value: result.Value}, true } func (cache *VersionConfigCache) GetMD5(platform, env string) ConfigValue { cache.RLock() defer cache.RUnlock() if value, ok := highestMD5(cache.md5s[configKey(platform)], env); ok { return value } if strings.TrimSpace(platform) != "" { value, _ := highestMD5(cache.md5s[configKey("")], env) return value } return ConfigValue{} } func highestMD5(items []*md5.MD5, env string) (ConfigValue, bool) { var result *md5.MD5 for _, item := range items { if item.External && configEnvMatches(item.EnvVersions, env) && (result == nil || CompareConfigVersion(item.Version, result.Version) > 0) { result = item } } if result == nil { return ConfigValue{}, false } return ConfigValue{Version: result.Version, Value: result.Value}, true } func configKey(platform string) string { return strings.TrimSpace(platform) } func configEnvMatches(envs []string, env string) bool { if len(envs) == 0 { return true } for _, item := range envs { if NormalizeEnvVersion(item) == env { return true } } return false } func CompareConfigVersion(left, right string) int { l, r := strings.Split(left, "."), strings.Split(right, ".") for i := 0; i < len(l) || i < len(r); i++ { lv, rv := 0, 0 if i < len(l) { for _, c := range l[i] { if c >= '0' && c <= '9' { lv = lv*10 + int(c-'0') } } } if i < len(r) { for _, c := range r[i] { if c >= '0' && c <= '9' { rv = rv*10 + int(c-'0') } } } if lv != rv { if lv < rv { return -1 } return 1 } } return 0 }