Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions dtos/fallbacktreatment.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,26 @@ type FallbackTreatment struct {

type FallbackTreatmentConfig struct {
GlobalFallbackTreatment *FallbackTreatment
byFlagFallbackTreatment map[string]FallbackTreatment
ByFlagFallbackTreatment map[string]FallbackTreatment
}

type FallbackTreatmentCalculator interface {
Resolve(flagName string, label string) FallbackTreatment
Resolve(flagName string, label *string) FallbackTreatment
}

type FallbackTreatmentCalculatorImp struct {
fallbackTreatmentConfig *FallbackTreatmentConfig
}

func NewFallbackTreatmentCalculatorImp(fallbackTreatmentConfig *FallbackTreatmentConfig) FallbackTreatmentCalculatorImp {
return FallbackTreatmentCalculatorImp{
func NewFallbackTreatmentCalculatorImp(fallbackTreatmentConfig *FallbackTreatmentConfig) FallbackTreatmentCalculator {
return &FallbackTreatmentCalculatorImp{
fallbackTreatmentConfig: fallbackTreatmentConfig,
}
}

func (f *FallbackTreatmentCalculatorImp) Resolve(flagName string, label *string) FallbackTreatment {
if f.fallbackTreatmentConfig != nil {
if byFlag := f.fallbackTreatmentConfig.byFlagFallbackTreatment; byFlag != nil {
if byFlag := f.fallbackTreatmentConfig.ByFlagFallbackTreatment; byFlag != nil {
if val, ok := byFlag[flagName]; ok {
return FallbackTreatment{
Treatment: val.Treatment,
Expand Down
2 changes: 1 addition & 1 deletion dtos/fallbacktreatment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ func TestFallbackTreatmentCalculatorResolve(t *testing.T) {
GlobalFallbackTreatment: &FallbackTreatment{
Treatment: "global_treatment",
},
byFlagFallbackTreatment: map[string]FallbackTreatment{
ByFlagFallbackTreatment: map[string]FallbackTreatment{
"flag1": {
Treatment: "flag1_treatment",
Config: &stringConfig,
Expand Down
32 changes: 23 additions & 9 deletions engine/evaluator/evaluator.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,11 @@ type Results struct {

// Evaluator struct is the main evaluator
type Evaluator struct {
splitStorage storage.SplitStorageConsumer
eng *engine.Engine
logger logging.LoggerInterface
ruleBuilder grammar.RuleBuilder
splitStorage storage.SplitStorageConsumer
eng *engine.Engine
logger logging.LoggerInterface
ruleBuilder grammar.RuleBuilder
fallbackTratmentCalculator dtos.FallbackTreatmentCalculator
}

// NewEvaluator instantiates an Evaluator struct and returns a reference to it
Expand All @@ -53,21 +54,25 @@ func NewEvaluator(
logger logging.LoggerInterface,
featureFlagRules []string,
ruleBasedSegmentRules []string,
fallbackTreatmentCalculator dtos.FallbackTreatmentCalculator,
) *Evaluator {
e := &Evaluator{
splitStorage: splitStorage,
eng: eng,
logger: logger,
splitStorage: splitStorage,
eng: eng,
logger: logger,
fallbackTratmentCalculator: fallbackTreatmentCalculator,
}
e.ruleBuilder = grammar.NewRuleBuilder(segmentStorage, ruleBasedSegmentStorage, largeSegmentStorage, featureFlagRules, ruleBasedSegmentRules, logger, e)
return e
}

func (e *Evaluator) evaluateTreatment(key string, bucketingKey string, featureFlag string, splitDto *dtos.SplitDTO, attributes map[string]interface{}) *Result {
var config *string
label := impressionlabels.SplitNotFound
if splitDto == nil {
e.logger.Warning(fmt.Sprintf("Feature flag %s not found, returning control.", featureFlag))
return &Result{Treatment: Control, Label: impressionlabels.SplitNotFound, Config: config}
fallbackTratment := e.fallbackTratmentCalculator.Resolve(featureFlag, &label)
e.logger.Warning(fmt.Sprintf("Feature flag %s not found, returning fallback treatment.", featureFlag))
return &Result{Treatment: fallbackTratment.Treatment, Label: *fallbackTratment.Label, Config: fallbackTratment.Config}
}

split := grammar.NewSplit(splitDto, e.logger, e.ruleBuilder)
Expand Down Expand Up @@ -113,6 +118,15 @@ func (e *Evaluator) evaluateTreatment(key string, bucketingKey string, featureFl
label = impressionlabels.NoConditionMatched
}

if *treatment == Control {
fallbackTreatment := e.fallbackTratmentCalculator.Resolve(featureFlag, &label)
return &Result{
Treatment: fallbackTreatment.Treatment,
Label: *fallbackTreatment.Label,
Config: fallbackTreatment.Config,
}
}

if _, ok := split.Configurations()[*treatment]; ok {
treatmentConfig := split.Configurations()[*treatment]
config = &treatmentConfig
Expand Down
46 changes: 36 additions & 10 deletions engine/evaluator/evaluator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,8 @@ func TestSplitWithoutConfigurations(t *testing.T) {
nil,
logger,
syncProxyFeatureFlagsRules,
syncProxyRuleBasedSegmentRules)
syncProxyRuleBasedSegmentRules,
nil)

key := "test"
result := evaluator.EvaluateFeature(key, &key, "mysplittest", nil)
Expand All @@ -333,7 +334,8 @@ func TestSplitWithtConfigurations(t *testing.T) {
nil,
logger,
syncProxyFeatureFlagsRules,
syncProxyRuleBasedSegmentRules)
syncProxyRuleBasedSegmentRules,
nil)

key := "test"
result := evaluator.EvaluateFeature(key, &key, "mysplittest2", nil)
Expand All @@ -358,7 +360,8 @@ func TestSplitWithtConfigurationsButKilled(t *testing.T) {
nil,
logger,
syncProxyFeatureFlagsRules,
syncProxyRuleBasedSegmentRules)
syncProxyRuleBasedSegmentRules,
nil)

key := "test"
result := evaluator.EvaluateFeature(key, &key, "mysplittest3", nil)
Expand All @@ -383,7 +386,8 @@ func TestSplitWithConfigurationsButKilledWithConfigsOnDefault(t *testing.T) {
nil,
logger,
syncProxyFeatureFlagsRules,
syncProxyRuleBasedSegmentRules)
syncProxyRuleBasedSegmentRules,
nil)

key := "test"
result := evaluator.EvaluateFeature(key, &key, "mysplittest4", nil)
Expand All @@ -399,6 +403,14 @@ func TestSplitWithConfigurationsButKilledWithConfigsOnDefault(t *testing.T) {

func TestMultipleEvaluations(t *testing.T) {
logger := logging.NewLogger(nil)
fallbackTreatmentConfig := dtos.FallbackTreatmentConfig{GlobalFallbackTreatment: &dtos.FallbackTreatment{
Treatment: "fallback",
},
ByFlagFallbackTreatment: map[string]dtos.FallbackTreatment{
"flag1": {
Treatment: "on",
},
}}

evaluator := NewEvaluator(
&mockStorage{},
Expand All @@ -408,7 +420,8 @@ func TestMultipleEvaluations(t *testing.T) {
nil,
logger,
syncProxyFeatureFlagsRules,
syncProxyRuleBasedSegmentRules)
syncProxyRuleBasedSegmentRules,
dtos.NewFallbackTreatmentCalculatorImp(&fallbackTreatmentConfig))

key := "test"
splits := []string{"mysplittest", "mysplittest2", "mysplittest3", "mysplittest4", "mysplittest5"}
Expand Down Expand Up @@ -442,7 +455,7 @@ func TestMultipleEvaluations(t *testing.T) {
t.Error("Unexpected configs")
}

if result.Evaluations["mysplittest5"].Treatment != "control" {
if result.Evaluations["mysplittest5"].Treatment != "fallback" {
t.Error("Wrong treatment result")
}
if result.Evaluations["mysplittest5"].Config != nil {
Expand All @@ -467,7 +480,8 @@ func TestNoConditionMatched(t *testing.T) {
nil,
logger,
syncProxyFeatureFlagsRules,
syncProxyRuleBasedSegmentRules)
syncProxyRuleBasedSegmentRules,
nil)

key := "test"
result := evaluator.EvaluateFeature(key, &key, "some", nil)
Expand Down Expand Up @@ -508,6 +522,15 @@ func TestEvaluationByFlagSets(t *testing.T) {
},
}

fallbackTreatmentConfig := dtos.FallbackTreatmentConfig{GlobalFallbackTreatment: &dtos.FallbackTreatment{
Treatment: "fallback",
},
ByFlagFallbackTreatment: map[string]dtos.FallbackTreatment{
"mysplittest5": {
Treatment: "on",
},
}}

evaluator := NewEvaluator(
mockedStorage,
nil,
Expand All @@ -516,7 +539,8 @@ func TestEvaluationByFlagSets(t *testing.T) {
nil,
logger,
syncProxyFeatureFlagsRules,
syncProxyRuleBasedSegmentRules)
syncProxyRuleBasedSegmentRules,
dtos.NewFallbackTreatmentCalculatorImp(&fallbackTreatmentConfig))
result := evaluator.EvaluateFeatureByFlagSets(key, &key, []string{"set1", "set2", "set3"}, nil)

if result.Evaluations["mysplittest"].Treatment != "off" {
Expand Down Expand Up @@ -547,7 +571,7 @@ func TestEvaluationByFlagSets(t *testing.T) {
t.Error("Unexpected configs")
}

if result.Evaluations["mysplittest5"].Treatment != "control" {
if result.Evaluations["mysplittest5"].Treatment != "on" {
t.Error("Wrong treatment result")
}
if result.Evaluations["mysplittest5"].Config != nil {
Expand Down Expand Up @@ -652,6 +676,7 @@ func TestPrerequisitesMatching(t *testing.T) {
logging.NewLogger(nil),
syncProxyFeatureFlagsRules,
syncProxyRuleBasedSegmentRules,
nil,
)

// Create split DTO with prerequisites
Expand Down Expand Up @@ -747,7 +772,8 @@ func TestEvaluationByFlagSetsASetEmpty(t *testing.T) {
nil,
logger,
syncProxyFeatureFlagsRules,
syncProxyRuleBasedSegmentRules)
syncProxyRuleBasedSegmentRules,
nil)
result := evaluator.EvaluateFeatureByFlagSets(key, &key, []string{"set2"}, nil)

if len(result.Evaluations) != 0 {
Expand Down
1 change: 1 addition & 0 deletions engine/grammar/dependency_test/dependency_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ func TestDependencyMatcher(t *testing.T) {
logger,
syncProxyFeatureFlagsRules,
syncProxyRuleBasedSegmentRules,
nil,
)

ruleBuilder := grammar.NewRuleBuilder(nil, nil, nil, syncProxyFeatureFlagsRules, syncProxyRuleBasedSegmentRules, logger, evaluator)
Expand Down