Skip to content

Commit c8a6d18

Browse files
committed
refactor
1 parent bf31c3e commit c8a6d18

File tree

6 files changed

+79
-65
lines changed

6 files changed

+79
-65
lines changed

client.go

Lines changed: 13 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66
"fmt"
77
"log/slog"
88
"strings"
9-
"sync"
109
"time"
1110

1211
"github.com/Flagsmith/flagsmith-go-client/v4/flagengine"
@@ -34,7 +33,7 @@ type Client struct {
3433
ctxLocalEval context.Context
3534
ctxAnalytics context.Context
3635

37-
environment state
36+
state environmentState
3837

3938
analyticsProcessor *AnalyticsProcessor
4039
log *slog.Logger
@@ -78,7 +77,7 @@ func NewClient(apiKey string, options ...Option) (*Client, error) {
7877
}
7978
}
8079

81-
if c.environment.IsOffline() {
80+
if c.state.IsOffline() {
8281
return c, nil
8382
}
8483
if c.defaultFlagHandler == nil && apiKey == "" {
@@ -174,7 +173,7 @@ func (c *Client) UpdateEnvironment(ctx context.Context) error {
174173
e := &APIError{response: resp.RawResponse}
175174
return c.handleError(e)
176175
}
177-
c.environment.SetEnvironment(env)
176+
c.state.SetEnvironment(&env)
178177

179178
c.log.Info("environment updated", "environment", env.APIKey)
180179
return nil
@@ -183,12 +182,12 @@ func (c *Client) UpdateEnvironment(ctx context.Context) error {
183182
// GetIdentitySegments returns the segments that this evaluation context is a part of. It requires a local environment
184183
// provided by [WithLocalEvaluation] and/or [WithOfflineHandler].
185184
func (c *Client) GetIdentitySegments(ec EvaluationContext) (s []*segments.SegmentModel, err error) {
186-
env, ok := c.environment.GetEnvironment()
185+
env, ok := c.state.GetEnvironment()
187186
if !ok {
188187
return s, errors.New("GetIdentitySegments called with no local environment available")
189188
}
190189
identity := c.getIdentityModel(ec.identifier, env.APIKey, ec.traits)
191-
return flagengine.GetIdentitySegments(env, &identity), nil
190+
return flagengine.GetIdentitySegments(env, identity), nil
192191
}
193192

194193
// BulkIdentify can be used to create/overwrite identities(with traits) in bulk
@@ -219,7 +218,7 @@ func (c *Client) BulkIdentify(ctx context.Context, batch []*IdentityTraits) erro
219218

220219
// GetEnvironmentFlags calls GetFlags for the default EvaluationContext.
221220
func (c *Client) GetEnvironmentFlags(ctx context.Context) (f Flags, err error) {
222-
if c.environment.IsOffline() || c.localEvaluation {
221+
if c.state.IsOffline() || c.localEvaluation {
223222
f, err = c.getEnvironmentFlagsFromEnvironment()
224223
} else {
225224
f, err = c.getEnvironmentFlagsFromAPI(ctx)
@@ -229,7 +228,7 @@ func (c *Client) GetEnvironmentFlags(ctx context.Context) (f Flags, err error) {
229228

230229
// GetIdentityFlags calls GetFlags using this identifier and traits as the EvaluationContext.
231230
func (c *Client) GetIdentityFlags(ctx context.Context, identifier string, traits map[string]interface{}) (f Flags, err error) {
232-
if c.environment.IsOffline() || c.localEvaluation {
231+
if c.state.IsOffline() || c.localEvaluation {
233232
f, err = c.getIdentityFlagsFromEnvironment(identifier, traits)
234233
} else {
235234
f, err = c.getIdentityFlagsFromAPI(ctx, identifier, traits)
@@ -240,7 +239,6 @@ func (c *Client) GetIdentityFlags(ctx context.Context, identifier string, traits
240239
// getEnvironmentFlagsFromAPI tries to contact the Flagsmith API to get the latest environment data.
241240
func (c *Client) getEnvironmentFlagsFromAPI(ctx context.Context) (Flags, error) {
242241
req := c.client.NewRequest()
243-
fmt.Println(c.baseURL)
244242
resp, err := req.
245243
SetContext(ctx).
246244
ForceContentType("application/json").
@@ -282,7 +280,7 @@ func (c *Client) getIdentityFlagsFromAPI(ctx context.Context, identifier string,
282280
}
283281

284282
func (c *Client) getEnvironmentFlagsFromEnvironment() (Flags, error) {
285-
env, ok := c.environment.GetEnvironment()
283+
env, ok := c.state.GetEnvironment()
286284
if !ok {
287285
return Flags{}, fmt.Errorf("getEnvironmentFlagsFromEnvironment: no local environment is available")
288286
}
@@ -295,12 +293,12 @@ func (c *Client) getEnvironmentFlagsFromEnvironment() (Flags, error) {
295293
}
296294

297295
func (c *Client) getIdentityFlagsFromEnvironment(identifier string, traits map[string]interface{}) (Flags, error) {
298-
env, ok := c.environment.GetEnvironment()
296+
env, ok := c.state.GetEnvironment()
299297
if !ok {
300298
return Flags{}, fmt.Errorf("getIdentityFlagsFromDocument: no local environment is available")
301299
}
302300
identity := c.getIdentityModel(identifier, env.APIKey, traits)
303-
featureStates := flagengine.GetIdentityFeatureStates(env, &identity)
301+
featureStates := flagengine.GetIdentityFeatureStates(env, identity)
304302
flags := makeFlagsFromFeatureStates(
305303
featureStates,
306304
c.analyticsProcessor,
@@ -332,18 +330,18 @@ func (c *Client) pollEnvironment(ctx context.Context) {
332330
}
333331
}
334332

335-
func (c *Client) getIdentityModel(identifier string, apiKey string, traits map[string]interface{}) identities.IdentityModel {
333+
func (c *Client) getIdentityModel(identifier string, apiKey string, traits map[string]interface{}) *identities.IdentityModel {
336334
identityTraits := make([]*enginetraits.TraitModel, 0, len(traits))
337335
for k, v := range traits {
338336
identityTraits = append(identityTraits, enginetraits.NewTrait(k, v))
339337
}
340338

341-
if identity, ok := c.environment.GetIdentityOverride(identifier); ok {
339+
if identity, ok := c.state.GetIdentityOverride(identifier); ok {
342340
identity.IdentityTraits = identityTraits
343341
return identity
344342
}
345343

346-
return identities.IdentityModel{
344+
return &identities.IdentityModel{
347345
Identifier: identifier,
348346
IdentityTraits: identityTraits,
349347
EnvironmentAPIKey: apiKey,
@@ -356,43 +354,3 @@ func (c *Client) handleError(err *APIError) *APIError {
356354
}
357355
return err
358356
}
359-
360-
type state struct {
361-
environment environments.EnvironmentModel
362-
offline bool
363-
mu sync.RWMutex
364-
365-
identityOverrides sync.Map
366-
}
367-
368-
func (es *state) GetEnvironment() (environments.EnvironmentModel, bool) {
369-
es.mu.RLock()
370-
defer es.mu.RUnlock()
371-
return es.environment, es.environment.APIKey != ""
372-
}
373-
374-
func (es *state) GetIdentityOverride(identifier string) (identities.IdentityModel, bool) {
375-
i, ok := es.identityOverrides.Load(identifier)
376-
if ok && i != nil {
377-
return i.(identities.IdentityModel), true
378-
}
379-
return identities.IdentityModel{}, ok
380-
}
381-
382-
func (es *state) SetEnvironment(env environments.EnvironmentModel) {
383-
es.mu.Lock()
384-
defer es.mu.Unlock()
385-
es.environment = env
386-
for _, id := range env.IdentityOverrides {
387-
es.identityOverrides.Store(id.Identifier, *id)
388-
}
389-
}
390-
391-
func (es *state) SetOfflineEnvironment(env environments.EnvironmentModel) {
392-
es.SetEnvironment(env)
393-
es.offline = true
394-
}
395-
396-
func (es *state) IsOffline() bool {
397-
return es.offline
398-
}

flagengine/engine.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ func GetEnvironmentFeatureState(environment environments.EnvironmentModel, featu
3434

3535
// GetIdentityFeatureStates returns a list of feature states for a given identity in a given environment.
3636
func GetIdentityFeatureStates(
37-
environment environments.EnvironmentModel,
37+
environment *environments.EnvironmentModel,
3838
identity *identities.IdentityModel,
3939
overrideTraits ...*traits.TraitModel,
4040
) []*features.FeatureStateModel {
@@ -52,7 +52,7 @@ func GetIdentityFeatureStates(
5252
}
5353

5454
func GetIdentityFeatureState(
55-
environment environments.EnvironmentModel,
55+
environment *environments.EnvironmentModel,
5656
identity *identities.IdentityModel,
5757
featureName string,
5858
overrideTraits ...*traits.TraitModel,
@@ -68,7 +68,7 @@ func GetIdentityFeatureState(
6868
}
6969

7070
func GetIdentitySegments(
71-
environment environments.EnvironmentModel,
71+
environment *environments.EnvironmentModel,
7272
identity *identities.IdentityModel,
7373
overrideTraits ...*traits.TraitModel,
7474
) []*segments.SegmentModel {
@@ -84,7 +84,7 @@ func GetIdentitySegments(
8484
}
8585

8686
func getIdentityFeatureStatesMap(
87-
environment environments.EnvironmentModel,
87+
environment *environments.EnvironmentModel,
8888
identity *identities.IdentityModel,
8989
overrideTraits ...*traits.TraitModel,
9090
) map[int]*features.FeatureStateModel {

offline_handler.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ import (
88
)
99

1010
type Environment interface {
11-
Environment() environments.EnvironmentModel
11+
Environment() *environments.EnvironmentModel
1212
}
1313

1414
type environment struct {
15-
model environments.EnvironmentModel
15+
model *environments.EnvironmentModel
1616
}
1717

18-
func (e environment) Environment() environments.EnvironmentModel {
18+
func (e environment) Environment() *environments.EnvironmentModel {
1919
return e.model
2020
}
2121

@@ -27,6 +27,6 @@ func ReadEnvironmentFromFile(name string) (env Environment, err error) {
2727
}
2828
var model environments.EnvironmentModel
2929
err = json.Unmarshal(file, &model)
30-
env = environment{model: model}
30+
env = environment{model: &model}
3131
return
3232
}

options.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ func WithProxy(url string) Option {
112112
// WithOfflineEnvironment sets the current environment and prevents Client from making network requests.
113113
func WithOfflineEnvironment(env Environment) Option {
114114
return func(c *Client) {
115-
c.environment.SetOfflineEnvironment(env.Environment())
115+
c.state.SetOfflineEnvironment(env.Environment())
116116
}
117117
}
118118

realtime.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ func (c *Client) startRealtimeUpdates(ctx context.Context) {
1818
panic("Failed to fetch the environment while configuring real-time updates")
1919
}
2020

21-
env, _ := c.environment.GetEnvironment()
21+
env, _ := c.state.GetEnvironment()
2222
envUpdatedAt := env.UpdatedAt
2323
log := c.log.With("environment", env.APIKey, "current_updated_at", &envUpdatedAt)
2424

state.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package flagsmith
2+
3+
import (
4+
"github.com/Flagsmith/flagsmith-go-client/v4/flagengine/environments"
5+
"github.com/Flagsmith/flagsmith-go-client/v4/flagengine/identities"
6+
"sync"
7+
)
8+
9+
// environmentState is a locally cached environments.EnvironmentModel.
10+
type environmentState struct {
11+
environment *environments.EnvironmentModel
12+
offline bool
13+
mu sync.RWMutex
14+
15+
identityOverrides sync.Map
16+
}
17+
18+
// GetEnvironment returns the current environment and indicates if it was initialised.
19+
func (cs *environmentState) GetEnvironment() (*environments.EnvironmentModel, bool) {
20+
cs.mu.RLock()
21+
defer cs.mu.RUnlock()
22+
if cs.environment == nil {
23+
return nil, false
24+
}
25+
return cs.environment, true
26+
}
27+
28+
func (cs *environmentState) GetIdentityOverride(identifier string) (*identities.IdentityModel, bool) {
29+
i, ok := cs.identityOverrides.Load(identifier)
30+
if ok && i != nil {
31+
return i.(*identities.IdentityModel), true
32+
}
33+
return nil, false
34+
}
35+
36+
func (cs *environmentState) SetEnvironment(env *environments.EnvironmentModel) {
37+
cs.mu.Lock()
38+
defer cs.mu.Unlock()
39+
40+
cs.environment = env
41+
42+
// clear previous overrides before storing the new ones
43+
cs.identityOverrides = sync.Map{}
44+
for _, id := range env.IdentityOverrides {
45+
cs.identityOverrides.Store(id.Identifier, id)
46+
}
47+
}
48+
49+
func (cs *environmentState) SetOfflineEnvironment(env *environments.EnvironmentModel) {
50+
cs.SetEnvironment(env)
51+
cs.offline = true
52+
}
53+
54+
func (cs *environmentState) IsOffline() bool {
55+
return cs.offline
56+
}

0 commit comments

Comments
 (0)