Skip to content

Commit

Permalink
flag api total confidence
Browse files Browse the repository at this point in the history
  • Loading branch information
vahidlazio committed May 17, 2024
1 parent 859dd88 commit 5293681
Show file tree
Hide file tree
Showing 26 changed files with 1,417 additions and 644 deletions.
5 changes: 5 additions & 0 deletions confidence/.fleet/run.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"configurations": [

]
}
170 changes: 170 additions & 0 deletions confidence/confidence.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
package confidence

import (
"context"
"fmt"
"net/http"
"reflect"
"strings"
)

type FlagResolver interface {
resolveFlag(ctx context.Context, flag string, defaultValue interface{},
evalCtx map[string]interface{}, expectedKind reflect.Kind) InterfaceResolutionDetail
}

type ContextProvider interface {
GetContext() map[string]interface{}
}

var (
SDK_ID = "SDK_ID_GO_PROVIDER"
SDK_VERSION = "0.1.8" // x-release-please-version
)

type Confidence struct {
parent ContextProvider
contextMap map[string]interface{}
Config APIConfig
ResolveClient ResolveClient
}

func (e Confidence) GetContext() map[string]interface{} {
currentMap := e.contextMap
parentMap := make(map[string]interface{})
if e.parent != nil {
parentMap = e.parent.GetContext()
}
for key, value := range parentMap {
currentMap[key] = value
}
return currentMap
}

type ConfidenceBuilder struct {
confidence Confidence
}

func (e ConfidenceBuilder) SetAPIConfig(config APIConfig) ConfidenceBuilder {
e.confidence.Config = config
return e
}

func (e ConfidenceBuilder) SetResolveClient(client ResolveClient) ConfidenceBuilder {
e.confidence.ResolveClient = client
return e
}

func (e ConfidenceBuilder) Build() Confidence {
if e.confidence.ResolveClient == nil {
e.confidence.ResolveClient = HttpResolveClient{Client: &http.Client{}, Config: e.confidence.Config}
}
e.confidence.contextMap = make(map[string]interface{})
return e.confidence
}

func NewConfidenceBuilder() ConfidenceBuilder {
return ConfidenceBuilder{
confidence: Confidence{},
}
}

func (e Confidence) putContext(key string, value interface{}) {
e.contextMap[key] = value
}

func (e Confidence) WithContext(context map[string]interface{}) Confidence {
return Confidence{
parent: &e,
contextMap: context,
Config: e.Config,
ResolveClient: e.ResolveClient,
}
}

func (e Confidence) GetBoolFlag(ctx context.Context, flag string, defaultValue bool) BoolResolutionDetail {
resp := e.ResolveFlag(ctx, flag, defaultValue, reflect.Bool)
return ToBoolResolutionDetail(resp, defaultValue)
}

func (e Confidence) GetBoolValue(ctx context.Context, flag string, defaultValue bool) bool {
return e.GetBoolFlag(ctx, flag, defaultValue).Value
}

func (e Confidence) GetIntFlag(ctx context.Context, flag string, defaultValue int64) IntResolutionDetail {
resp := e.ResolveFlag(ctx, flag, defaultValue, reflect.Int64)
return ToIntResolutionDetail(resp, defaultValue)
}

func (e Confidence) GetIntValue(ctx context.Context, flag string, defaultValue int64) int64 {
return e.GetIntFlag(ctx, flag, defaultValue).Value
}

func (e Confidence) GetDoubleFlag(ctx context.Context, flag string, defaultValue float64) FloatResolutionDetail {
resp := e.ResolveFlag(ctx, flag, defaultValue, reflect.Float64)
return ToFloatResolutionDetail(resp, defaultValue)
}

func (e Confidence) GetDoubleValue(ctx context.Context, flag string, defaultValue float64) float64 {
return e.GetDoubleFlag(ctx, flag, defaultValue).Value
}

func (e Confidence) GetStringFlag(ctx context.Context, flag string, defaultValue string) StringResolutionDetail {
resp := e.ResolveFlag(ctx, flag, defaultValue, reflect.String)
return ToStringResolutionDetail(resp, defaultValue)
}

func (e Confidence) GetStringValue(ctx context.Context, flag string, defaultValue string) string {
return e.GetStringFlag(ctx, flag, defaultValue).Value
}

func (e Confidence) GetObjectFlag(ctx context.Context, flag string, defaultValue string) InterfaceResolutionDetail {
resp := e.ResolveFlag(ctx, flag, defaultValue, reflect.Map)
return resp
}

func (e Confidence) GetObjectValue(ctx context.Context, flag string, defaultValue string) interface{} {
return e.GetObjectFlag(ctx, flag, defaultValue).Value
}

func (e Confidence) ResolveFlag(ctx context.Context, flag string, defaultValue interface{}, expectedKind reflect.Kind) InterfaceResolutionDetail {
flagName, propertyPath := splitFlagString(flag)

requestFlagName := fmt.Sprintf("flags/%s", flagName)
resp, err := e.ResolveClient.SendResolveRequest(ctx,
ResolveRequest{ClientSecret: e.Config.APIKey,
Flags: []string{requestFlagName}, Apply: true, EvaluationContext: e.contextMap,
Sdk: sdk{Id: SDK_ID, Version: SDK_VERSION}})

if err != nil {
return processResolveError(err, defaultValue)
}
if len(resp.ResolvedFlags) == 0 {
return InterfaceResolutionDetail{
Value: defaultValue,
ResolutionDetail: ResolutionDetail{
Variant: "",
Reason: ErrorReason,
ErrorCode: FlagNotFoundCode,
ErrorMessage: "Flag not found",
FlagMetadata: nil,
},
}
}

resolvedFlag := resp.ResolvedFlags[0]
if resolvedFlag.Flag != requestFlagName {
return InterfaceResolutionDetail{
Value: defaultValue,
ResolutionDetail: ResolutionDetail{
Variant: "",
Reason: ErrorReason,
ErrorCode: FlagNotFoundCode,
ErrorMessage: fmt.Sprintf("unexpected flag '%s' from remote", strings.TrimPrefix(resolvedFlag.Flag, "flags/")),
FlagMetadata: nil,
},
}
}

return processResolvedFlag(resolvedFlag, defaultValue, expectedKind, propertyPath)
}
Loading

0 comments on commit 5293681

Please sign in to comment.