Skip to content

Commit 260f5e6

Browse files
authored
Merge pull request #5 from volcengine/feature/support_domain
Feature/support domain
2 parents 0e3c065 + 6241ba6 commit 260f5e6

File tree

5 files changed

+85
-3
lines changed

5 files changed

+85
-3
lines changed

client/client.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"github.com/volcengine/datatester-go-sdk/handler"
1717
"github.com/volcengine/datatester-go-sdk/log"
1818
"github.com/volcengine/datatester-go-sdk/meta/manager"
19+
"github.com/volcengine/datatester-go-sdk/utils"
1920
)
2021

2122
type AbClient struct {
@@ -180,7 +181,10 @@ func (t *AbClient) GetAllExperimentConfigs(decisionId string,
180181
continue
181182
}
182183
for k, v := range confMap {
183-
configs[k] = v
184+
existConfig, conflict := configs[k]
185+
if !conflict || utils.IsHigherPriorityConfig(existConfig, v) {
186+
configs[k] = v
187+
}
184188
}
185189
}
186190
t.updateUserAbInfo(decisionId, experiment2variant)
@@ -212,7 +216,10 @@ func (t *AbClient) getAllExperimentConfigs4Activate(variantKey, decisionId strin
212216
continue
213217
}
214218
for k, v := range confMap {
215-
configs[k] = v
219+
existConfig, conflict := configs[k]
220+
if !conflict || utils.IsHigherPriorityConfig(existConfig, v) {
221+
configs[k] = v
222+
}
216223
}
217224
vid2ExperimentIdMap[variant.Id] = variant.ExperimentId
218225
}
@@ -426,7 +433,10 @@ func (t *AbClient) GetAllFeatureConfigs(decisionId string,
426433
continue
427434
}
428435
for k, v := range confMap {
429-
configs[k] = v
436+
existConfig, conflict := configs[k]
437+
if !conflict || utils.IsHigherPriorityConfig(existConfig, v) {
438+
configs[k] = v
439+
}
430440
}
431441
}
432442
return configs, nil

distributor/distributor.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,11 @@ func (v *VariantsDistributor) tabExperimentVariant(c *config.ProductConfig, expe
254254
if !ok {
255255
return e.Variant{}, fmt.Errorf("no layer[%s] exist in config", experiment.LayerID)
256256
}
257+
// check 互斥域
258+
hitDomain := layer.HitDomain(decisionId)
259+
if !hitDomain {
260+
return e.Variant{}, nil
261+
}
257262
eid, err := v.tabLayerExperimentId(layer, decisionId)
258263
if err != nil || len(eid) == 0 || eid != experiment.Id {
259264
return e.Variant{}, err

entities/domain.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package entities
2+
3+
import (
4+
"strings"
5+
6+
"github.com/volcengine/datatester-go-sdk/distributor/bucketer"
7+
)
8+
9+
type Domain struct {
10+
ID string `json:"id"`
11+
Name string `json:"name"`
12+
HashStrategy string `json:"hash_strategy"`
13+
Begin uint32 `json:"begin"`
14+
Length uint32 `json:"length"`
15+
}
16+
17+
// Hit 方法检查给定的 decisionID 是否在当前 Domain 的索引范围内
18+
func (d Domain) Hit(decisionID string) bool {
19+
// 通过连接 decisionID 和 d.Name 获取流量桶索引
20+
index, err := bucketer.NewMmh3BucketService().GetTrafficBucketIndex(
21+
strings.Join([]string{decisionID, d.Name}, ":"))
22+
// 如果获取索引过程中出现错误,返回 false
23+
if err != nil {
24+
return false
25+
}
26+
// 如果索引值在 d.Begin 和 d.Begin + d.Length 之间,返回 true,否则返回 false
27+
return index >= d.Begin && index < d.Begin+d.Length
28+
}

entities/layer.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,25 @@ type Layer struct {
1414
Name string `json:"name"`
1515
TrafficAllocation []release.TrafficAllocation `json:"traffic_allocation"`
1616
ExperimentIds []string `json:"experiment_ids"`
17+
Domain *Domain `json:"domain"`
18+
ParentDomains []Domain `json:"parent_domains"`
19+
}
20+
21+
// HitDomain 方法用于检查给定的 decisionID 是否命中当前层及其所有父域
22+
func (l Layer) HitDomain(decisionID string) bool {
23+
// 层不属于互斥域,直接返回
24+
if l.Domain == nil || l.Domain.ID == "0" {
25+
return true
26+
}
27+
hit := l.Domain.Hit(decisionID)
28+
if !hit {
29+
return false
30+
}
31+
for _, d := range l.ParentDomains {
32+
hit = d.Hit(decisionID)
33+
if !hit {
34+
return false
35+
}
36+
}
37+
return true
1738
}

utils/conflict.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package utils
2+
3+
import (
4+
"strconv"
5+
"strings"
6+
)
7+
8+
func IsHigherPriorityConfig(existConf, newConf map[string]interface{}) bool {
9+
vid1 := existConf["vid"].(string)
10+
vid2 := newConf["vid"].(string)
11+
v1, err1 := strconv.ParseInt(vid1, 10, 64)
12+
v2, err2 := strconv.ParseInt(vid2, 10, 64)
13+
// 转换失败,则按照字符串对比,一般不会出现
14+
if err1 != nil || err2 != nil {
15+
return strings.Compare(vid2, vid1) < 0
16+
}
17+
return v2 < v1
18+
}

0 commit comments

Comments
 (0)