From b33361b4bae51be0077fe6d829bf7e79502f7dce Mon Sep 17 00:00:00 2001 From: "lihaoyu.henrylee" Date: Tue, 3 Sep 2024 11:56:48 +0800 Subject: [PATCH] =?UTF-8?q?feature(domain):=20=E5=A2=9E=E5=8A=A0=E5=AF=B9?= =?UTF-8?q?=E4=BA=8E=E4=BA=92=E6=96=A5=E5=9F=9F=E7=9A=84=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- distributor/distributor.go | 5 +++++ entities/domain.go | 28 ++++++++++++++++++++++++++++ entities/layer.go | 21 +++++++++++++++++++++ 3 files changed, 54 insertions(+) create mode 100644 entities/domain.go diff --git a/distributor/distributor.go b/distributor/distributor.go index 238fb25..658052f 100644 --- a/distributor/distributor.go +++ b/distributor/distributor.go @@ -254,6 +254,11 @@ func (v *VariantsDistributor) tabExperimentVariant(c *config.ProductConfig, expe if !ok { return e.Variant{}, fmt.Errorf("no layer[%s] exist in config", experiment.LayerID) } + // check 互斥域 + hitDomain := layer.HitDomain(decisionId) + if !hitDomain { + return e.Variant{}, nil + } eid, err := v.tabLayerExperimentId(layer, decisionId) if err != nil || len(eid) == 0 || eid != experiment.Id { return e.Variant{}, err diff --git a/entities/domain.go b/entities/domain.go new file mode 100644 index 0000000..b1d2b1c --- /dev/null +++ b/entities/domain.go @@ -0,0 +1,28 @@ +package entities + +import ( + "strings" + + "github.com/volcengine/datatester-go-sdk/distributor/bucketer" +) + +type Domain struct { + ID string `json:"id"` + Name string `json:"name"` + HashStrategy string `json:"hash_strategy"` + Begin uint32 `json:"begin"` + Length uint32 `json:"length"` +} + +// Hit 方法检查给定的 decisionID 是否在当前 Domain 的索引范围内 +func (d Domain) Hit(decisionID string) bool { + // 通过连接 decisionID 和 d.Name 获取流量桶索引 + index, err := bucketer.NewMmh3BucketService().GetTrafficBucketIndex( + strings.Join([]string{decisionID, d.Name}, ":")) + // 如果获取索引过程中出现错误,返回 false + if err != nil { + return false + } + // 如果索引值在 d.Begin 和 d.Begin + d.Length 之间,返回 true,否则返回 false + return index >= d.Begin && index < d.Begin+d.Length +} diff --git a/entities/layer.go b/entities/layer.go index 82290c0..352a3ed 100644 --- a/entities/layer.go +++ b/entities/layer.go @@ -14,4 +14,25 @@ type Layer struct { Name string `json:"name"` TrafficAllocation []release.TrafficAllocation `json:"traffic_allocation"` ExperimentIds []string `json:"experiment_ids"` + Domain *Domain `json:"domain"` + ParentDomains []Domain `json:"parent_domains"` +} + +// HitDomain 方法用于检查给定的 decisionID 是否命中当前层及其所有父域 +func (l Layer) HitDomain(decisionID string) bool { + // 层不属于互斥域,直接返回 + if l.Domain == nil || l.Domain.ID == "0" { + return true + } + hit := l.Domain.Hit(decisionID) + if !hit { + return false + } + for _, d := range l.ParentDomains { + hit = d.Hit(decisionID) + if !hit { + return false + } + } + return true }