package task import ( "dsbqj-admin/model/mongo/version" "dsbqj-admin/pkg/util" "strings" "sync" "github.com/kamva/mgm/v3" "go.mongodb.org/mongo-driver/bson" ) const ( releaseEnvVersion = "release" trialEnvVersion = "trial" ) var VersionTask *Versions type Versions struct { sync.Mutex VPlatforms util.SafeMap[string, *PlatformVersions] } type PlatformVersions struct { VList util.SafeArray[*version.Version] VMap util.SafeMap[string, *version.Version] } func NormalizeEnvVersion(envVersion string) string { if strings.EqualFold(strings.TrimSpace(envVersion), trialEnvVersion) { return trialEnvVersion } return releaseEnvVersion } func VersionInit() *Versions { VersionTask = new(Versions) return VersionTask } func (this *Versions) Exec() { VersionConfigTask.Reload() var versions = make([]*version.Version, 0) err := mgm.Coll(&version.Version{}).SimpleFind(&versions, bson.M{}) if err == nil { this.VPlatforms.Clear() for _, v := range versions { key := strings.TrimSpace(v.Platform) if _, ok := this.VPlatforms.Get(key); !ok { this.VPlatforms.Set(key, new(PlatformVersions)) } platformVersions, _ := this.VPlatforms.Get(key) platformVersions.VList.Push(v) platformVersions.VMap.Set(versionMapKey(v.Version, NormalizeEnvVersion(v.EnvVersion)), v) } } } func (this *Versions) Check(version string, platform string, envVersion string) *version.Version { envVersionRequired := strings.TrimSpace(envVersion) != "" if strings.EqualFold(strings.TrimSpace(envVersion), "develop") { envVersion = trialEnvVersion } envVersion = NormalizeEnvVersion(envVersion) platform = strings.TrimSpace(platform) if result := this.checkPlatform(platform, version, envVersion, envVersionRequired); result != nil { return result } // Historical records did not carry platform. They remain a read-only fallback // until data is migrated, and never override platform-specific records. if platform != "" { if result := this.checkPlatform("", version, envVersion, envVersionRequired); result != nil { return result } } candidates := []string{platform} if platform != "" { candidates = append(candidates, "") } for _, candidate := range candidates { if result := this.checkPlatform(candidate, version, releaseEnvVersion, true); result != nil { return result } if result := this.checkPlatform(candidate, "", releaseEnvVersion, true); result != nil { return result } } return nil } func (this *Versions) checkPlatform(platform, version, envVersion string, envVersionRequired bool) *version.Version { platformVersions, ok := this.VPlatforms.Get(strings.TrimSpace(platform)) if !ok { return nil } if strings.TrimSpace(version) == "" { return this.defaultVersion(platformVersions, envVersion) } if envVersionRequired { if data, ok := platformVersions.VMap.Get(versionMapKey(version, envVersion)); ok { return data } return this.defaultVersion(platformVersions, envVersion) } if data, ok := platformVersions.VMap.Get(versionMapKey(version, releaseEnvVersion)); ok { return data } if data, ok := platformVersions.VMap.Get(versionMapKey(version, trialEnvVersion)); ok { return data } return nil } func (this *Versions) defaultVersion(platformVersions *PlatformVersions, envVersion string) *version.Version { var fallback *version.Version var selected *version.Version for _, v := range platformVersions.VList.View() { if NormalizeEnvVersion(v.EnvVersion) != envVersion { continue } if fallback == nil || CompareConfigVersion(v.Version, fallback.Version) > 0 { fallback = v } if v.Default && (selected == nil || CompareConfigVersion(v.Version, selected.Version) > 0) { selected = v } } if selected != nil { return selected } return fallback } func versionMapKey(version string, envVersion string) string { return envVersion + ":" + version } func (this *Versions) Servers(platform string) []*version.Version { var res = make([]*version.Version, 0) if platformVersions, ok := this.VPlatforms.Get(strings.TrimSpace(platform)); ok { res = append(res, platformVersions.VList.View()...) } if len(res) == 0 && strings.TrimSpace(platform) != "" { if legacyVersions, ok := this.VPlatforms.Get(""); ok { res = append(res, legacyVersions.VList.View()...) } } return res }