Skip to content

Commit

Permalink
[FFM-9476]: Optimize memory usage (#126)
Browse files Browse the repository at this point in the history
This change supports improved memory usage of the evaluator code.
It introduces a new function on the query interface GetFlagMap().  This returns a map of flags.

This is more optimal as the GetFlag function can also use a underlying map, it removes the need to maintain both a list
and a map of flags for the caller of the evaluator.
  • Loading branch information
davejohnston authored Sep 26, 2023
1 parent 82306ec commit 4fd36ec
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 6 deletions.
21 changes: 15 additions & 6 deletions evaluation/evaluator.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package evaluation

import (
"encoding/json"
"errors"
"fmt"
"regexp"
"sort"
Expand All @@ -27,11 +28,16 @@ const (
equalSensitiveOperator = "equal_sensitive"
)

var (
ErrNilFlag = errors.New("flag is nil")
)

// Query provides methods for segment and flag retrieval
type Query interface {
GetSegment(identifier string) (rest.Segment, error)
GetFlag(identifier string) (rest.FeatureConfig, error)
GetFlags() ([]rest.FeatureConfig, error)
GetFlagMap() (map[string]*rest.FeatureConfig, error)
}

// FlagVariations list of FlagVariations
Expand Down Expand Up @@ -329,7 +335,7 @@ func (e Evaluator) EvaluateAll(target *Target) (FlagVariations, error) {
// takes uses feature store.List function to get all the flags.
func (e Evaluator) evaluateAll(target *Target) ([]FlagVariation, error) {
var variations []FlagVariation
flags, err := e.query.GetFlags()
flags, err := e.query.GetFlagMap()
if err != nil {
return variations, err
}
Expand Down Expand Up @@ -358,29 +364,32 @@ func (e Evaluator) evaluate(identifier string, target *Target) (FlagVariation, e
return FlagVariation{}, err
}

variation, err := e.getVariationForTheFlag(flag, target)
variation, err := e.getVariationForTheFlag(&flag, target)
if err != nil {
return FlagVariation{}, err
}
return FlagVariation{flag.Feature, flag.Kind, variation}, nil
}

// evaluates the flag and returns a proper variation.
func (e Evaluator) getVariationForTheFlag(flag rest.FeatureConfig, target *Target) (rest.Variation, error) {
func (e Evaluator) getVariationForTheFlag(flag *rest.FeatureConfig, target *Target) (rest.Variation, error) {
if flag == nil {
return rest.Variation{}, ErrNilFlag
}

if flag.Prerequisites != nil {
prereq, err := e.checkPreRequisite(&flag, target)
prereq, err := e.checkPreRequisite(flag, target)
if err != nil || !prereq {
return findVariation(flag.Variations, flag.OffVariation)
}
}
variation, err := e.evaluateFlag(flag, target)
variation, err := e.evaluateFlag(*flag, target)
if err != nil {
return rest.Variation{}, err
}
if e.postEvalCallback != nil {
data := PostEvalData{
FeatureConfig: &flag,
FeatureConfig: flag,
Target: target,
Variation: &variation,
}
Expand Down
8 changes: 8 additions & 0 deletions evaluation/evaluator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,14 @@ func (m TestRepository) GetFlags() ([]rest.FeatureConfig, error) {
return flags, nil
}

func (m TestRepository) GetFlagMap() (map[string]*rest.FeatureConfig, error) {
var flags map[string]*rest.FeatureConfig
for _, f := range m.flags {
flags[f.Feature] = &f
}
return flags, nil
}

func TestNewEvaluator(t *testing.T) {
noOpLogger := logger.NewNoOpLogger()
eval, _ := NewEvaluator(testRepo, nil, noOpLogger)
Expand Down
6 changes: 6 additions & 0 deletions pkg/repository/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ type Repository interface {
GetFlag(identifier string) (rest.FeatureConfig, error)
GetSegment(identifier string) (rest.Segment, error)
GetFlags() ([]rest.FeatureConfig, error)
GetFlagMap() (map[string]*rest.FeatureConfig, error)

SetFlag(featureConfig rest.FeatureConfig, initialLoad bool)
SetFlags(initialLoad bool, envID string, featureConfig ...rest.FeatureConfig)
Expand Down Expand Up @@ -120,6 +121,11 @@ func (r FFRepository) GetFlags() ([]rest.FeatureConfig, error) {
return []rest.FeatureConfig{}, nil
}

// GetFlagMap returns all flags as a mao /* Not Implemented *.
func (r FFRepository) GetFlagMap() (map[string]*rest.FeatureConfig, error) {
return map[string]*rest.FeatureConfig{}, nil
}

func (r FFRepository) getSegmentAndCache(identifier string, cacheable bool) (rest.Segment, error) {
segmentKey := formatSegmentKey(identifier)
flag, ok := r.cache.Get(segmentKey)
Expand Down

0 comments on commit 4fd36ec

Please sign in to comment.