Skip to content

Commit 8ddb7db

Browse files
authored
ensure global state initialized with new client (#256)
creating new client skips the init for global sdk configs - but as kenny commented, sdk configs shouldn't be shared across clients. This will now be its own instance on the client
1 parent 15ebece commit 8ddb7db

10 files changed

+31
-26
lines changed

client.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,11 @@ func newClientImpl(sdkKey string, options *Options) (*Client, *initContext) {
5050
err := errors.New(InvalidSDKKeyError)
5151
panic(err)
5252
}
53+
sdkConfigs := newSDKConfigs()
5354
transport := newTransport(sdkKey, options)
54-
logger := newLogger(transport, options, diagnostics, errorBoundary)
55-
evaluator := newEvaluator(transport, errorBoundary, options, diagnostics, sdkKey)
55+
logger := newLogger(transport, options, diagnostics, errorBoundary, sdkConfigs)
56+
evaluator := newEvaluator(transport, errorBoundary, options, diagnostics, sdkKey, sdkConfigs)
57+
5658
client := &Client{
5759
sdkKey: sdkKey,
5860
evaluator: evaluator,

evaluator.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,9 @@ func newEvaluator(
103103
options *Options,
104104
diagnostics *diagnostics,
105105
sdkKey string,
106+
sdkConfigs *SDKConfigs,
106107
) *evaluator {
107-
store := newStore(transport, errorBoundary, options, diagnostics, sdkKey)
108+
store := newStore(transport, errorBoundary, options, diagnostics, sdkKey, sdkConfigs)
108109
defer func() {
109110
if err := recover(); err != nil {
110111
errorBoundary.logException(toError(err))

global_state.go

-13
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import (
1010
// Instead, define an accessor below using the Mutex lock
1111
type GlobalState struct {
1212
logger *OutputLogger
13-
sdkConfig *SDKConfigs
1413
sessionID string
1514
mu sync.RWMutex
1615
}
@@ -42,15 +41,3 @@ func InitializeGlobalSessionID() {
4241
defer global.mu.Unlock()
4342
global.sessionID = uuid.NewString()
4443
}
45-
46-
func SDKConfig() *SDKConfigs {
47-
global.mu.RLock()
48-
defer global.mu.RUnlock()
49-
return global.sdkConfig
50-
}
51-
52-
func InitializeGlobalSDKConfig() {
53-
global.mu.Lock()
54-
defer global.mu.Unlock()
55-
global.sdkConfig = &SDKConfigs{}
56-
}

logger.go

+5-3
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,10 @@ type logger struct {
5555
options *Options
5656
errorBoundary *errorBoundary
5757
samplingKeySet *TTLSet
58+
SDKConfigs *SDKConfigs
5859
}
5960

60-
func newLogger(transport *transport, options *Options, diagnostics *diagnostics, errorBoundary *errorBoundary) *logger {
61+
func newLogger(transport *transport, options *Options, diagnostics *diagnostics, errorBoundary *errorBoundary, sdkConfigs *SDKConfigs) *logger {
6162
loggingInterval := time.Minute
6263
maxEvents := 1000
6364
if options.LoggingInterval > 0 {
@@ -77,6 +78,7 @@ func newLogger(transport *transport, options *Options, diagnostics *diagnostics,
7778
options: options,
7879
errorBoundary: errorBoundary,
7980
samplingKeySet: NewTTLSet(),
81+
SDKConfigs: sdkConfigs,
8082
}
8183

8284
go log.backgroundFlush()
@@ -369,8 +371,8 @@ func (l *logger) determineSampling(entityType EntityType,
369371

370372
shadowShouldLog := true
371373
env := l.options.GetSDKEnvironmentTier()
372-
samplingMode, _ = SDKConfig().GetConfigStrValue("sampling_mode")
373-
specialCaseSamplingRate, _ := SDKConfig().GetConfigIntValue("special_case_sampling_rate")
374+
samplingMode, _ = l.SDKConfigs.GetConfigStrValue("sampling_mode")
375+
specialCaseSamplingRate, _ := l.SDKConfigs.GetConfigIntValue("special_case_sampling_rate")
374376
specialCaseRules := map[string]bool{
375377
"disabled": true,
376378
"default": true,

logger_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ func TestLog(t *testing.T) {
1515
opt := &Options{
1616
API: testServer.URL,
1717
}
18-
InitializeGlobalSDKConfig()
1918
transport := newTransport("secret", opt)
2019
errorBoundary := newErrorBoundary("secret", opt, nil)
21-
logger := newLogger(transport, opt, nil, errorBoundary)
20+
sdkConfigs := newSDKConfigs()
21+
logger := newLogger(transport, opt, nil, errorBoundary, sdkConfigs)
2222

2323
user := User{
2424
UserID: "123",

output_logger_test.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ func TestLogEventErrors(t *testing.T) {
3131
diagnostics := newDiagnostics(opts)
3232
transport := newTransport("secret", opts)
3333
errorBoundary := newErrorBoundary("secret", opts, nil)
34-
logger := newLogger(transport, opts, diagnostics, errorBoundary)
34+
sdkConfigs := newSDKConfigs()
35+
logger := newLogger(transport, opts, diagnostics, errorBoundary, sdkConfigs)
3536

3637
user := User{
3738
UserID: "123",

sdk_configs.go

+7
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,13 @@ type SDKConfigs struct {
1111
mu sync.RWMutex
1212
}
1313

14+
func newSDKConfigs() *SDKConfigs {
15+
return &SDKConfigs{
16+
flags: make(map[string]bool),
17+
configs: make(map[string]interface{}),
18+
}
19+
}
20+
1421
func (s *SDKConfigs) SetFlags(newFlags map[string]bool) {
1522
s.mu.Lock()
1623
s.flags = newFlags

statsig.go

-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ func Initialize(sdkKey string) InitializeDetails {
3030
func InitializeWithOptions(sdkKey string, options *Options) InitializeDetails {
3131
InitializeGlobalOutputLogger(options.OutputLoggerOptions)
3232
InitializeGlobalSessionID()
33-
InitializeGlobalSDKConfig()
3433
if IsInitialized() {
3534
Logger().Log("Statsig is already initialized.", nil)
3635
return InitializeDetails{Success: true, Source: instance.evaluator.store.source}

store.go

+7-2
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ type store struct {
143143
sdkKey string
144144
isPolling bool
145145
bootstrapValues string
146+
sdkConfigs *SDKConfigs
146147
}
147148

148149
var syncOutdatedMax = 2 * time.Minute
@@ -153,6 +154,7 @@ func newStore(
153154
options *Options,
154155
diagnostics *diagnostics,
155156
sdkKey string,
157+
sdkConfigs *SDKConfigs,
156158
) *store {
157159
configSyncInterval := 10 * time.Second
158160
idListSyncInterval := time.Minute
@@ -172,6 +174,7 @@ func newStore(
172174
diagnostics,
173175
sdkKey,
174176
options.BootstrapValues,
177+
sdkConfigs,
175178
)
176179
}
177180

@@ -185,6 +188,7 @@ func newStoreInternal(
185188
diagnostics *diagnostics,
186189
sdkKey string,
187190
bootstrapValues string,
191+
sdkConfigs *SDKConfigs,
188192
) *store {
189193
store := &store{
190194
featureGates: make(map[string]configSpec),
@@ -203,6 +207,7 @@ func newStoreInternal(
203207
sdkKey: sdkKey,
204208
isPolling: false,
205209
bootstrapValues: bootstrapValues,
210+
sdkConfigs: sdkConfigs,
206211
}
207212
return store
208213
}
@@ -479,8 +484,8 @@ func (s *store) setConfigSpecs(specs downloadConfigSpecResponse) (bool, bool) {
479484
}
480485
}
481486

482-
SDKConfig().SetConfigs(specs.SDKConfigs)
483-
SDKConfig().SetFlags(specs.SDKFlags)
487+
s.sdkConfigs.SetConfigs(specs.SDKConfigs)
488+
s.sdkConfigs.SetFlags(specs.SDKFlags)
484489
s.mu.Lock()
485490
s.featureGates = newGates
486491
s.dynamicConfigs = newConfigs

store_test.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,8 @@ func TestStoreSync(t *testing.T) {
113113
n := newTransport("secret-123", opt)
114114
d := newDiagnostics(opt)
115115
e := newErrorBoundary("client-key", opt, d)
116-
s := newStoreInternal(n, time.Second, time.Second, nil, e, nil, d, "secret-123", "")
116+
c := newSDKConfigs()
117+
s := newStoreInternal(n, time.Second, time.Second, nil, e, nil, d, "secret-123", "", c)
117118
s.initialize(nil)
118119

119120
if s.getGatesCount() != 1 {

0 commit comments

Comments
 (0)