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.
128 lines
2.7 KiB
128 lines
2.7 KiB
package abtest |
|
|
|
import ( |
|
"context" |
|
"time" |
|
|
|
"go-common/app/interface/main/app-resource/conf" |
|
expdao "go-common/app/interface/main/app-resource/dao/abtest" |
|
"go-common/app/interface/main/app-resource/model/experiment" |
|
"go-common/app/service/main/resource/model" |
|
"go-common/library/log" |
|
|
|
farm "github.com/dgryski/go-farm" |
|
) |
|
|
|
var ( |
|
_emptyExperiment = []*experiment.Experiment{} |
|
_defaultExperiment = map[int8][]*experiment.Experiment{ |
|
model.PlatAndroid: []*experiment.Experiment{ |
|
&experiment.Experiment{ |
|
ID: 10, |
|
Name: "默认值", |
|
Strategy: "default_value", |
|
Desc: "默认值为不匹配处理", |
|
TrafficGroup: "0", |
|
}, |
|
}, |
|
} |
|
) |
|
|
|
type Service struct { |
|
dao *expdao.Dao |
|
// tick |
|
tick time.Duration |
|
epm map[int8][]*experiment.Experiment |
|
c *conf.Config |
|
} |
|
|
|
func New(c *conf.Config) (s *Service) { |
|
s = &Service{ |
|
c: c, |
|
dao: expdao.New(c), |
|
// tick |
|
tick: time.Duration(c.Tick), |
|
epm: map[int8][]*experiment.Experiment{}, |
|
} |
|
s.loadAbTest() |
|
go s.tickproc() |
|
return |
|
} |
|
|
|
// TemporaryABTests 临时的各种abtest垃圾需求 |
|
func (s *Service) TemporaryABTests(c context.Context, buvid string) (tests *experiment.ABTestV2) { |
|
id := farm.Hash32([]byte(buvid)) |
|
n := int(id % 100) |
|
autoPlay := 1 |
|
if n > s.c.ABTest.Range { |
|
autoPlay = 2 |
|
} |
|
tests = &experiment.ABTestV2{ |
|
AutoPlay: autoPlay, |
|
} |
|
return |
|
} |
|
|
|
func (s *Service) Experiment(c context.Context, plat int8, build int) (eps []*experiment.Experiment) { |
|
if es, ok := s.epm[plat]; ok { |
|
LOOP: |
|
for _, ep := range es { |
|
for _, l := range ep.Limit { |
|
if model.InvalidBuild(build, l.Build, l.Condition) { |
|
continue LOOP |
|
} |
|
} |
|
eps = append(eps, ep) |
|
} |
|
} |
|
if eps == nil { |
|
if es, ok := _defaultExperiment[plat]; ok { |
|
eps = es |
|
} else { |
|
eps = _emptyExperiment |
|
} |
|
} |
|
return |
|
} |
|
|
|
// tickproc tick load cache. |
|
func (s *Service) tickproc() { |
|
for { |
|
time.Sleep(s.tick) |
|
s.loadAbTest() |
|
} |
|
} |
|
|
|
func (s *Service) loadAbTest() { |
|
c := context.TODO() |
|
lm, err := s.dao.ExperimentLimit(c) |
|
if err != nil { |
|
log.Error("s.dao.ExperimentLimit error(%v)", err) |
|
return |
|
} |
|
ids := make([]int64, 0, len(lm)) |
|
for id := range lm { |
|
ids = append(ids, id) |
|
} |
|
if len(ids) == 0 { |
|
return |
|
} |
|
eps, err := s.dao.ExperimentByIDs(c, ids) |
|
if err != nil { |
|
log.Error("s.dao.ExperimentByIDs(%v) error(%v)", ids, err) |
|
return |
|
} |
|
epm := make(map[int8][]*experiment.Experiment, len(eps)) |
|
for _, ep := range eps { |
|
if l, ok := lm[ep.ID]; ok { |
|
ep.Limit = l |
|
} |
|
epm[ep.Plat] = append(epm[ep.Plat], ep) |
|
} |
|
s.epm = epm |
|
} |
|
|
|
// AbServer is |
|
func (s *Service) AbServer(c context.Context, buvid, device, mobiAPP, filteredStr string, build int, mid int64) (a interface{}, err error) { |
|
return s.dao.AbServer(c, buvid, device, mobiAPP, filteredStr, build, mid) |
|
}
|
|
|