Skip to content

Commit 75392c2

Browse files
committed
Streaming connections are now closed when you call Close on a client
1 parent 6bb5f78 commit 75392c2

File tree

2 files changed

+37
-13
lines changed

2 files changed

+37
-13
lines changed

client/client.go

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package client
33
import (
44
"context"
55
"encoding/json"
6+
"errors"
67
"fmt"
78
"net/http"
89
"strings"
@@ -46,7 +47,6 @@ type CfClient struct {
4647
config *config
4748
environmentID string
4849
token string
49-
cancelFunc context.CancelFunc
5050
streamConnected bool
5151
streamConnectedLock sync.RWMutex
5252
authenticated chan struct{}
@@ -55,17 +55,14 @@ type CfClient struct {
5555
initializedLock sync.RWMutex
5656
analyticsService *analyticsservice.AnalyticsService
5757
clusterIdentifier string
58+
stop chan struct{}
59+
stopped bool
5860
}
5961

6062
// NewCfClient creates a new client instance that connects to CF with the default configuration.
6163
// For advanced configuration options use ConfigOptions functions
6264
func NewCfClient(sdkKey string, options ...ConfigOption) (*CfClient, error) {
6365

64-
var (
65-
ctx context.Context
66-
err error
67-
)
68-
6966
// functional options for config
7067
config := newDefaultConfig()
7168
for _, opt := range options {
@@ -81,8 +78,8 @@ func NewCfClient(sdkKey string, options ...ConfigOption) (*CfClient, error) {
8178
analyticsService: analyticsService,
8279
clusterIdentifier: "1",
8380
postEvalChan: make(chan evaluation.PostEvalData),
81+
stop: make(chan struct{}),
8482
}
85-
ctx, client.cancelFunc = context.WithCancel(context.Background())
8683

8784
if sdkKey == "" {
8885
return client, types.ErrSdkCantBeEmpty
@@ -97,13 +94,20 @@ func NewCfClient(sdkKey string, options ...ConfigOption) (*CfClient, error) {
9794
return nil, err
9895
}
9996

100-
go client.initAuthentication(ctx)
101-
102-
go client.setAnalyticsServiceClient(ctx)
97+
client.start()
98+
return client, nil
99+
}
103100

104-
go client.pullCronJob(ctx)
101+
func (c *CfClient) start() {
102+
ctx, cancel := context.WithCancel(context.Background())
103+
go func() {
104+
<-c.stop
105+
cancel()
106+
}()
105107

106-
return client, nil
108+
go c.initAuthentication(ctx)
109+
go c.setAnalyticsServiceClient(ctx)
110+
go c.pullCronJob(ctx)
107111
}
108112

109113
// PostEvaluateProcessor push the data to the analytics service
@@ -432,7 +436,14 @@ func (c *CfClient) JSONVariation(key string, target *evaluation.Target, defaultV
432436
// Close shuts down the Feature Flag client. After calling this, the client
433437
// should no longer be used
434438
func (c *CfClient) Close() error {
435-
c.cancelFunc()
439+
c.mux.Lock()
440+
defer c.mux.Unlock()
441+
if c.stopped {
442+
return errors.New("client already closed")
443+
}
444+
close(c.stop)
445+
446+
c.stopped = true
436447
return nil
437448
}
438449

client/client_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,3 +199,16 @@ var FeatureConfigsResponse = func(req *http.Request) (*http.Response, error) {
199199

200200
return httpmock.NewJsonResponse(200, FeatureConfigResponse)
201201
}
202+
203+
func TestCfClient_Close(t *testing.T) {
204+
client, err := newClient(&http.Client{})
205+
if err != nil {
206+
t.Error(err)
207+
}
208+
209+
t.Log("When I close the client for the first time I should not get an error")
210+
assert.Nil(t, client.Close())
211+
212+
t.Log("When I close the client for the second time I should an error")
213+
assert.NotNil(t, client.Close())
214+
}

0 commit comments

Comments
 (0)