Skip to content

Commit bafe94e

Browse files
Remove Fetch From Server (#263)
kong test: statsig-io/kong#3354
1 parent 3550033 commit bafe94e

File tree

4 files changed

+52
-123
lines changed

4 files changed

+52
-123
lines changed

client.go

+30-111
Original file line numberDiff line numberDiff line change
@@ -372,56 +372,27 @@ type GetLayerOptions struct {
372372
PersistedValues UserPersistedValues
373373
}
374374

375-
type gateResponse struct {
376-
Name string `json:"name"`
377-
Value bool `json:"value"`
378-
RuleID string `json:"rule_id"`
379-
}
380-
381-
type configResponse struct {
382-
Name string `json:"name"`
383-
Value map[string]interface{} `json:"value"`
384-
RuleID string `json:"rule_id"`
385-
}
386-
387-
type checkGateInput struct {
388-
GateName string `json:"gateName"`
389-
User User `json:"user"`
390-
StatsigMetadata statsigMetadata `json:"statsigMetadata"`
391-
}
392-
393-
type getConfigInput struct {
394-
ConfigName string `json:"configName"`
395-
User User `json:"user"`
396-
StatsigMetadata statsigMetadata `json:"statsigMetadata"`
397-
}
398-
399375
func (c *Client) checkGateImpl(user User, name string, context *evalContext) FeatureGate {
400376
if !c.verifyUser(user) {
401377
return *NewGate(name, false, "", "", nil)
402378
}
403379
user = normalizeUser(user, *c.options)
404380
res := c.evaluator.evalGate(user, name, context)
405-
if res.FetchFromServer {
406-
serverRes := fetchGate(user, name, c.transport)
407-
res = &evalResult{Value: serverRes.Value, RuleID: serverRes.RuleID}
408-
} else {
409-
exposure := c.logger.logGateExposure(user, name, res, context)
381+
exposure := c.logger.logGateExposure(user, name, res, context)
410382

411-
if c.options.EvaluationCallbacks.GateEvaluationCallback != nil {
412-
if c.options.EvaluationCallbacks.IncludeDisabledExposures || !context.DisableLogExposures {
413-
c.options.EvaluationCallbacks.GateEvaluationCallback(name, res.Value, exposure)
414-
} else {
415-
c.options.EvaluationCallbacks.GateEvaluationCallback(name, res.Value, nil)
416-
}
383+
if c.options.EvaluationCallbacks.GateEvaluationCallback != nil {
384+
if c.options.EvaluationCallbacks.IncludeDisabledExposures || !context.DisableLogExposures {
385+
c.options.EvaluationCallbacks.GateEvaluationCallback(name, res.Value, exposure)
386+
} else {
387+
c.options.EvaluationCallbacks.GateEvaluationCallback(name, res.Value, nil)
417388
}
389+
}
418390

419-
if c.options.EvaluationCallbacks.ExposureCallback != nil {
420-
if c.options.EvaluationCallbacks.IncludeDisabledExposures || !context.DisableLogExposures {
421-
c.options.EvaluationCallbacks.ExposureCallback(name, exposure)
422-
} else {
423-
c.options.EvaluationCallbacks.ExposureCallback(name, nil)
424-
}
391+
if c.options.EvaluationCallbacks.ExposureCallback != nil {
392+
if c.options.EvaluationCallbacks.IncludeDisabledExposures || !context.DisableLogExposures {
393+
c.options.EvaluationCallbacks.ExposureCallback(name, exposure)
394+
} else {
395+
c.options.EvaluationCallbacks.ExposureCallback(name, nil)
425396
}
426397
}
427398
return *NewGate(name, res.Value, res.RuleID, res.GroupName, res.EvaluationDetails)
@@ -434,32 +405,27 @@ func (c *Client) getConfigImpl(user User, name string, context *evalContext) Dyn
434405
user = normalizeUser(user, *c.options)
435406
res := c.evaluator.evalConfig(user, name, context)
436407
config := *NewConfig(name, res.JsonValue, res.RuleID, res.GroupName, res.EvaluationDetails)
437-
if res.FetchFromServer {
438-
res = c.fetchConfigFromServer(user, name)
439-
config = *NewConfig(name, res.JsonValue, res.RuleID, res.GroupName, res.EvaluationDetails)
440-
} else {
441-
exposure := c.logger.logConfigExposure(user, name, res, context)
408+
exposure := c.logger.logConfigExposure(user, name, res, context)
442409

443-
if context.IsExperiment && c.options.EvaluationCallbacks.ExperimentEvaluationCallback != nil {
444-
if c.options.EvaluationCallbacks.IncludeDisabledExposures || !context.DisableLogExposures {
445-
c.options.EvaluationCallbacks.ExperimentEvaluationCallback(name, config, exposure)
446-
} else {
447-
c.options.EvaluationCallbacks.ExperimentEvaluationCallback(name, config, nil)
448-
}
449-
} else if c.options.EvaluationCallbacks.ConfigEvaluationCallback != nil {
450-
if c.options.EvaluationCallbacks.IncludeDisabledExposures || !context.DisableLogExposures {
451-
c.options.EvaluationCallbacks.ConfigEvaluationCallback(name, config, exposure)
452-
} else {
453-
c.options.EvaluationCallbacks.ConfigEvaluationCallback(name, config, nil)
454-
}
410+
if context.IsExperiment && c.options.EvaluationCallbacks.ExperimentEvaluationCallback != nil {
411+
if c.options.EvaluationCallbacks.IncludeDisabledExposures || !context.DisableLogExposures {
412+
c.options.EvaluationCallbacks.ExperimentEvaluationCallback(name, config, exposure)
413+
} else {
414+
c.options.EvaluationCallbacks.ExperimentEvaluationCallback(name, config, nil)
415+
}
416+
} else if c.options.EvaluationCallbacks.ConfigEvaluationCallback != nil {
417+
if c.options.EvaluationCallbacks.IncludeDisabledExposures || !context.DisableLogExposures {
418+
c.options.EvaluationCallbacks.ConfigEvaluationCallback(name, config, exposure)
419+
} else {
420+
c.options.EvaluationCallbacks.ConfigEvaluationCallback(name, config, nil)
455421
}
422+
}
456423

457-
if c.options.EvaluationCallbacks.ExposureCallback != nil {
458-
if c.options.EvaluationCallbacks.IncludeDisabledExposures || !context.DisableLogExposures {
459-
c.options.EvaluationCallbacks.ExposureCallback(name, exposure)
460-
} else {
461-
c.options.EvaluationCallbacks.ExposureCallback(name, nil)
462-
}
424+
if c.options.EvaluationCallbacks.ExposureCallback != nil {
425+
if c.options.EvaluationCallbacks.IncludeDisabledExposures || !context.DisableLogExposures {
426+
c.options.EvaluationCallbacks.ExposureCallback(name, exposure)
427+
} else {
428+
c.options.EvaluationCallbacks.ExposureCallback(name, nil)
463429
}
464430
}
465431
return config
@@ -473,10 +439,6 @@ func (c *Client) getLayerImpl(user User, name string, context *evalContext) Laye
473439
user = normalizeUser(user, *c.options)
474440
res := c.evaluator.evalLayer(user, name, context)
475441

476-
if res.FetchFromServer {
477-
res = c.fetchConfigFromServer(user, name)
478-
}
479-
480442
logFunc := func(layer Layer, parameterName string) {
481443
exposure := c.logger.logLayerExposure(user, layer, parameterName, res, context)
482444
if c.options.EvaluationCallbacks.LayerEvaluationCallback != nil {
@@ -498,41 +460,6 @@ func (c *Client) getLayerImpl(user User, name string, context *evalContext) Laye
498460
return *NewLayer(name, res.JsonValue, res.RuleID, res.GroupName, &logFunc, res.ConfigDelegate)
499461
}
500462

501-
func fetchGate(user User, gateName string, t *transport) gateResponse {
502-
input := &checkGateInput{
503-
GateName: gateName,
504-
User: user,
505-
StatsigMetadata: t.metadata,
506-
}
507-
var res gateResponse
508-
_, err := t.post("/check_gate", input, &res, RequestOptions{}, nil)
509-
if err != nil {
510-
return gateResponse{
511-
Name: gateName,
512-
Value: false,
513-
RuleID: "",
514-
}
515-
}
516-
return res
517-
}
518-
519-
func fetchConfig(user User, configName string, t *transport) configResponse {
520-
input := &getConfigInput{
521-
ConfigName: configName,
522-
User: user,
523-
StatsigMetadata: t.metadata,
524-
}
525-
var res configResponse
526-
_, err := t.post("/get_config", input, &res, RequestOptions{}, nil)
527-
if err != nil {
528-
return configResponse{
529-
Name: configName,
530-
RuleID: "",
531-
}
532-
}
533-
return res
534-
}
535-
536463
func normalizeUser(user User, options Options) User {
537464
env := make(map[string]string)
538465
// Copy to avoid data race. We modify the map below.
@@ -548,11 +475,3 @@ func normalizeUser(user User, options Options) User {
548475
user.StatsigEnvironment = env
549476
return user
550477
}
551-
552-
func (c *Client) fetchConfigFromServer(user User, configName string) *evalResult {
553-
serverRes := fetchConfig(user, configName, c.transport)
554-
return &evalResult{
555-
JsonValue: serverRes.Value,
556-
RuleID: serverRes.RuleID,
557-
}
558-
}

evaluation_details.go

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const (
1919
ReasonLocalOverride EvaluationReason = "LocalOverride"
2020
ReasonUnrecognized EvaluationReason = "Unrecognized"
2121
ReasonPersisted EvaluationReason = "Persisted"
22+
ReasonUnsupported EvaluationReason = "Unsupported"
2223
)
2324

2425
type EvaluationDetails struct {

evaluation_test.go

+9-1
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,15 @@ func test_helper(apiOverride string, t *testing.T) {
128128
for _, entry := range d.Entries {
129129
u := entry.User
130130
for gate, serverResult := range entry.GatesV2 {
131-
sdkResult := c.evaluator.evalGate(u, gate, &evalContext{Hash: "none"})
131+
if gate == "test_not_in_id_list" {
132+
totalChecks -= 3
133+
continue
134+
}
135+
if gate == "test_id_list" {
136+
totalChecks -= 3
137+
continue
138+
}
139+
sdkResult := c.evaluator.evalGate(u, gate, &evalContext{Hash: "none"})
132140
if sdkResult.Value != serverResult.Value {
133141
t.Errorf("Values are different for gate %s. SDK got %t but server is %t. User is %+v",
134142
gate, sdkResult.Value, serverResult.Value, u)

evaluator.go

+12-11
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import (
1616
type evalResult struct {
1717
Value bool `json:"value"`
1818
JsonValue map[string]interface{} `json:"json_value"`
19-
FetchFromServer bool `json:"fetch_from_server"`
19+
Unsupported bool `json:"unsupported"`
2020
RuleID string `json:"rule_id"`
2121
GroupName string `json:"group_name"`
2222
SecondaryExposures []SecondaryExposure `json:"secondary_exposures"`
@@ -376,7 +376,8 @@ func (e *evaluator) eval(user User, spec configSpec, depth int, context *evalCon
376376
if spec.Enabled {
377377
for _, rule := range spec.Rules {
378378
r := e.evalRule(user, rule, depth+1, context)
379-
if r.FetchFromServer {
379+
if r.Unsupported {
380+
r.EvaluationDetails = e.createEvaluationDetails(ReasonUnsupported)
380381
return r
381382
}
382383
exposures = e.cleanExposures(append(exposures, r.SecondaryExposures...))
@@ -487,14 +488,14 @@ func getUnitID(user User, idType string) string {
487488
func (e *evaluator) evalRule(user User, rule configRule, depth int, context *evalContext) *evalResult {
488489
var exposures = make([]SecondaryExposure, 0)
489490
var deviceMetadata *DerivedDeviceMetadata
490-
var finalResult = &evalResult{Value: true, FetchFromServer: false}
491+
var finalResult = &evalResult{Value: true, Unsupported: false}
491492
for _, cond := range rule.Conditions {
492493
res := e.evalCondition(user, cond, depth+1, context)
493494
if !res.Value {
494495
finalResult.Value = false
495496
}
496-
if res.FetchFromServer {
497-
finalResult.FetchFromServer = true
497+
if res.Unsupported {
498+
finalResult.Unsupported = true
498499
}
499500
deviceMetadata = assignDerivedDeviceMetadata(res, deviceMetadata)
500501
exposures = append(exposures, res.SecondaryExposures...)
@@ -521,8 +522,8 @@ func (e *evaluator) evalCondition(user User, cond configCondition, depth int, co
521522
return &evalResult{Value: false}
522523
}
523524
result := e.evalGateImpl(user, dependentGateName, depth+1, context)
524-
if result.FetchFromServer {
525-
return &evalResult{FetchFromServer: true}
525+
if result.Unsupported {
526+
return &evalResult{Unsupported: true}
526527
}
527528
allExposures := result.SecondaryExposures
528529
if !strings.HasPrefix(dependentGateName, "segment:") {
@@ -563,11 +564,11 @@ func (e *evaluator) evalCondition(user User, cond configCondition, depth int, co
563564
case strings.EqualFold(condType, "unit_id"):
564565
value = getUnitID(user, cond.IDType)
565566
default:
566-
return &evalResult{FetchFromServer: true}
567+
return &evalResult{Unsupported: true}
567568
}
568569

569570
pass := false
570-
server := false
571+
unsupported := false
571572
switch {
572573
case strings.EqualFold(op, "gt"):
573574
pass = compareNumbers(value, cond.TargetValue, func(x, y float64) bool { return x > y })
@@ -717,9 +718,9 @@ func (e *evaluator) evalCondition(user User, cond configCondition, depth int, co
717718
}
718719
default:
719720
pass = false
720-
server = true
721+
unsupported = true
721722
}
722-
return &evalResult{Value: pass, FetchFromServer: server, DerivedDeviceMetadata: deviceMetadata}
723+
return &evalResult{Value: pass, Unsupported: unsupported, DerivedDeviceMetadata: deviceMetadata}
723724
}
724725

725726
func getFromUser(user User, field string) interface{} {

0 commit comments

Comments
 (0)