You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
264 lines
6.3 KiB
264 lines
6.3 KiB
package version |
|
|
|
import ( |
|
"context" |
|
"time" |
|
|
|
"go-common/app/interface/main/app-resource/conf" |
|
verdao "go-common/app/interface/main/app-resource/dao/version" |
|
"go-common/app/interface/main/app-resource/model" |
|
"go-common/app/interface/main/app-resource/model/version" |
|
"go-common/library/ecode" |
|
"go-common/library/log" |
|
|
|
farm "github.com/dgryski/go-farm" |
|
) |
|
|
|
const ( |
|
_defaultChannel = "bili" |
|
) |
|
|
|
var ( |
|
_emptyVersion = []*version.Version{} |
|
_emptyVersionSo = []*version.VersionSo{} |
|
) |
|
|
|
// Service version service. |
|
type Service struct { |
|
dao *verdao.Dao |
|
cache map[int8][]*version.Version |
|
upCache map[int8]map[string][]*version.VersionUpdate |
|
uplimitCache map[int][]*version.UpdateLimit |
|
soCache map[string][]*version.VersionSo |
|
increCache map[int8]map[string][]*version.Incremental |
|
rnCache map[string]map[string]*version.Rn |
|
tick time.Duration |
|
} |
|
|
|
// New new a version service. |
|
func New(c *conf.Config) (s *Service) { |
|
s = &Service{ |
|
dao: verdao.New(c), |
|
tick: time.Duration(c.Tick), |
|
cache: map[int8][]*version.Version{}, |
|
upCache: map[int8]map[string][]*version.VersionUpdate{}, |
|
uplimitCache: map[int][]*version.UpdateLimit{}, |
|
soCache: map[string][]*version.VersionSo{}, |
|
increCache: map[int8]map[string][]*version.Incremental{}, |
|
rnCache: map[string]map[string]*version.Rn{}, |
|
} |
|
s.load() |
|
go s.loadproc() |
|
return |
|
} |
|
|
|
// Version return version |
|
func (s *Service) Version(plat int8) (res []*version.Version, err error) { |
|
if res = s.cache[plat]; res == nil { |
|
res = _emptyVersion |
|
} |
|
return |
|
} |
|
|
|
// VersionUpdate return version |
|
func (s *Service) VersionUpdate(build int, plat int8, buvid, sdkint, channel, module, oldID string) (res *version.VersionUpdate, err error) { |
|
var ( |
|
gvu, tmp []*version.VersionUpdate |
|
) |
|
if vup, ok := s.upCache[plat]; ok { |
|
if tmp, ok = vup[channel]; !ok || len(tmp) == 0 { |
|
if plat == model.PlatAndroidTVYST { |
|
err = ecode.NotModified |
|
return |
|
} |
|
if tmp, ok = vup[_defaultChannel]; !ok || len(tmp) == 0 { |
|
err = ecode.NotModified |
|
return |
|
} |
|
} |
|
for _, t := range tmp { |
|
tu := &version.VersionUpdate{} |
|
*tu = *t |
|
gvu = append(gvu, tu) |
|
} |
|
} else { |
|
err = ecode.NotModified |
|
return |
|
} |
|
LOOP: |
|
for _, vu := range gvu { |
|
if build >= vu.Build { |
|
err = ecode.NotModified |
|
return |
|
} |
|
if vu.IsGray == 1 { |
|
if len(vu.SdkIntList) > 0 { |
|
if _, ok := vu.SdkIntList[sdkint]; !ok { |
|
continue LOOP |
|
} |
|
} |
|
if module != vu.Model && vu.Model != "" { |
|
continue LOOP |
|
} |
|
if buvid != "" { |
|
id := farm.Hash32([]byte(buvid)) |
|
n := int(id % 100) |
|
if vu.BuvidStart > n || n > vu.BuvidEnd { |
|
continue LOOP |
|
} |
|
} |
|
} |
|
if limit, ok := s.uplimitCache[vu.Id]; ok { |
|
var tmpl bool |
|
for i, l := range limit { |
|
if i+1 <= len(limit)-1 { |
|
if ((l.Conditions == "gt" && limit[i+1].Conditions == "lt") && (l.BuildLimit < limit[i+1].BuildLimit)) || |
|
((l.Conditions == "lt" && limit[i+1].Conditions == "gt") && (l.BuildLimit > limit[i+1].BuildLimit)) { |
|
if (l.Conditions == "gt" && limit[i+1].Conditions == "lt") && |
|
(build > l.BuildLimit && build < limit[i+1].BuildLimit) { |
|
res = vu |
|
break LOOP |
|
} else if (l.Conditions == "lt" && limit[i+1].Conditions == "gt") && |
|
(build < l.BuildLimit && build > limit[i+1].BuildLimit) { |
|
res = vu |
|
break LOOP |
|
} else { |
|
tmpl = true |
|
continue |
|
} |
|
} |
|
} |
|
if tmpl { |
|
tmpl = false |
|
continue |
|
} |
|
if model.InvalidBuild(build, l.BuildLimit, l.Conditions) { |
|
continue |
|
} else { |
|
res = vu |
|
break LOOP |
|
} |
|
} |
|
} else { |
|
res = vu |
|
break LOOP |
|
} |
|
} |
|
if res == nil { |
|
err = ecode.NotModified |
|
return |
|
} |
|
res.Incre = s.versionIncrementals(plat, res.Build, oldID) |
|
return |
|
} |
|
|
|
// versionIncrementals version incrementals |
|
func (s *Service) versionIncrementals(plat int8, build int, oldID string) (ver *version.Incremental) { |
|
if v, ok := s.increCache[plat]; ok { |
|
if vers, ok := v[oldID]; ok { |
|
for _, value := range vers { |
|
if value.Build == build { |
|
ver = value |
|
return |
|
} |
|
} |
|
} |
|
} |
|
return |
|
} |
|
|
|
// VersionSo return version_so |
|
func (s *Service) VersionSo(build, seed, sdkint int, name, model string) (vsdesc *version.VersionSoDesc, err error) { |
|
vSo := s.soCache[name] |
|
if len(vSo) == 0 { |
|
err = ecode.NotModified |
|
return |
|
} |
|
vsdesc = &version.VersionSoDesc{ |
|
Package: vSo[0].Package, |
|
Name: vSo[0].Name, |
|
Description: vSo[0].Description, |
|
Clear: vSo[0].Clear, |
|
} |
|
for _, value := range vSo { |
|
if value.Min_build > build || (seed > 0 && seed%100 >= value.Coverage) || (sdkint != value.Sdkint && value.Sdkint != 0) || (model != value.Model && value.Model != "" && value.Model != "*") { |
|
continue |
|
} |
|
vsdesc.Versions = append(vsdesc.Versions, value) |
|
} |
|
if vsdesc.Versions == nil { |
|
vsdesc.Versions = _emptyVersionSo |
|
} |
|
return |
|
} |
|
|
|
// VersionRn return version_rn |
|
func (s *Service) VersionRn(version, deploymentKey, bundleID string) (vrn *version.Rn, err error) { |
|
if v, ok := s.rnCache[deploymentKey]; ok { |
|
if vrn, ok = v[version]; !ok { |
|
err = ecode.NotModified |
|
} else if vrn.BundleID == bundleID { |
|
err = ecode.NotModified |
|
} |
|
} else { |
|
err = ecode.NotModified |
|
} |
|
return |
|
} |
|
|
|
// load cache data |
|
func (s *Service) load() { |
|
ver, err := s.dao.All(context.TODO()) |
|
if err != nil { |
|
log.Error("version s.dao.All() error(%v)", err) |
|
return |
|
} |
|
s.cache = ver |
|
upver, err := s.dao.Updates(context.TODO()) |
|
if err != nil { |
|
log.Error("version s.dao.GetUpdate() error(%v)", err) |
|
return |
|
} |
|
s.upCache = upver |
|
log.Info("version cacheproc success") |
|
sover, err := s.dao.Sos(context.TODO()) |
|
if err != nil { |
|
log.Error("version s.dao.Sos() error(%v)", err) |
|
return |
|
} |
|
uplimit, err := s.dao.Limits(context.TODO()) |
|
if err != nil { |
|
log.Error("version s.dao.Limits() error(%v)", err) |
|
return |
|
} |
|
s.uplimitCache = uplimit |
|
s.soCache = sover |
|
log.Info("versionso cacheproc success") |
|
increver, err := s.dao.Incrementals(context.TODO()) |
|
if err != nil { |
|
log.Error("version s.dao.Incrementals error(%v)", err) |
|
return |
|
} |
|
s.increCache = increver |
|
log.Info("versionIncre cacheproc success") |
|
rn, err := s.dao.Rn(context.TODO()) |
|
if err != nil { |
|
log.Error("version s.dao.Rn error(%v)", err) |
|
return |
|
} |
|
s.rnCache = rn |
|
log.Info("versionRn cacheproc success") |
|
} |
|
|
|
// cacheproc load cache data |
|
func (s *Service) loadproc() { |
|
for { |
|
time.Sleep(s.tick) |
|
s.load() |
|
} |
|
} |
|
|
|
// Close dao |
|
func (s *Service) Close() { |
|
s.dao.Close() |
|
}
|
|
|