Skip to content

Commit

Permalink
Allow using target app ID directly for GCIR (#223)
Browse files Browse the repository at this point in the history
Atlassian insists that they need a way to pass the target app directly to GCIR. I don't like supporting this as an official use case of the SDK. So just enable this under the hood

>Ask
Support client initialize response creation by target app parameter (by ID good if ID can be looked up by name) instead of client key.
Currently the target app is looked up by the supplied client key parameter and used to filter the gates, dynamic configs, and layers. We would like to supply the target app directly.
This will ideally reduce the number of client keys required in some cases (i.e. use of kill-switches and configuration where we don’t want to log events in the client) and ease integration with our new Statsig sidecar.
Impact
Streamlining SSR use cases and Feature Flag Service providing dynamic configuration
Fewer client keys required (potentially)
  • Loading branch information
kenny-statsig authored Aug 27, 2024
1 parent 2c24056 commit f89dc82
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 15 deletions.
8 changes: 1 addition & 7 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -298,13 +298,7 @@ func (c *Client) GetClientInitializeResponseImpl(user User, options *GCIROptions
return *new(ClientInitializeResponse)
}
user = normalizeUser(user, *c.options)
includeLocalOverrides := options.IncludeLocalOverrides
clientKey := options.ClientKey
hashAlgorithm := options.HashAlgorithm
if hashAlgorithm != "none" && hashAlgorithm != "djb2" {
hashAlgorithm = "sha256"
}
response := c.evaluator.getClientInitializeResponse(user, clientKey, includeLocalOverrides, hashAlgorithm)
response := c.evaluator.getClientInitializeResponse(user, options)
if response.Time == 0 {
c.errorBoundary.logException(errors.New("empty response from server"))
}
Expand Down
19 changes: 13 additions & 6 deletions client_initialize_response.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,12 @@ func mergeMaps(a map[string]interface{}, b map[string]interface{}) {
func getClientInitializeResponse(
user User,
e *evaluator,
clientKey string,
includeLocalOverrides bool,
hashAlgorithm string,
options *GCIROptions,
) ClientInitializeResponse {
hashAlgorithm := options.HashAlgorithm
if hashAlgorithm != "none" && hashAlgorithm != "djb2" {
hashAlgorithm = "sha256"
}
context := StatsigContext{Caller: "getClientInitializeResponse", Hash: hashAlgorithm}

evalResultToBaseResponse := func(name string, eval *evalResult) (string, baseSpecInitializeResponse) {
Expand All @@ -82,7 +84,7 @@ func getClientInitializeResponse(
}
gateToResponse := func(gateName string, spec configSpec) (string, GateInitializeResponse) {
evalRes := &evalResult{}
if includeLocalOverrides {
if options.IncludeLocalOverrides {
if gateOverride, hasOverride := e.getGateOverrideEval(gateName); hasOverride {
evalRes = gateOverride
} else {
Expand All @@ -100,7 +102,7 @@ func getClientInitializeResponse(
}
configToResponse := func(configName string, spec configSpec) (string, ConfigInitializeResponse) {
evalRes := &evalResult{}
if includeLocalOverrides {
if options.IncludeLocalOverrides {
if configOverride, hasOverride := e.getConfigOverrideEval(configName); hasOverride {
evalRes = configOverride
} else {
Expand Down Expand Up @@ -175,7 +177,12 @@ func getClientInitializeResponse(
return hashedName, result
}

appId, _ := e.store.getAppIDForSDKKey(clientKey)
var appId string
if options.TargetAppID != "" {
appId = options.TargetAppID
} else {
appId, _ = e.store.getAppIDForSDKKey(options.ClientKey)
}
featureGates := make(map[string]GateInitializeResponse)
dynamicConfigs := make(map[string]ConfigInitializeResponse)
layerConfigs := make(map[string]LayerInitializeResponse)
Expand Down
7 changes: 5 additions & 2 deletions evaluator.go
Original file line number Diff line number Diff line change
Expand Up @@ -327,8 +327,11 @@ func (e *evaluator) OverrideLayer(layer string, val map[string]interface{}) {

// Gets all evaluated values for the given user.
// These values can then be given to a Statsig Client SDK via bootstrapping.
func (e *evaluator) getClientInitializeResponse(user User, clientKey string, includeLocalOverrides bool, hashAlgorithm string) ClientInitializeResponse {
return getClientInitializeResponse(user, e, clientKey, includeLocalOverrides, hashAlgorithm)
func (e *evaluator) getClientInitializeResponse(
user User,
options *GCIROptions,
) ClientInitializeResponse {
return getClientInitializeResponse(user, e, options)
}

func (e *evaluator) cleanExposures(exposures []SecondaryExposure, hashAlgorithm string) []SecondaryExposure {
Expand Down
1 change: 1 addition & 0 deletions statsig.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ type Environment struct {
type GCIROptions struct {
IncludeLocalOverrides bool
ClientKey string
TargetAppID string
HashAlgorithm string
}

Expand Down

0 comments on commit f89dc82

Please sign in to comment.