diff --git a/featureflag/global.go b/featureflag/global.go index 1c75c4f..4eeafdb 100644 --- a/featureflag/global.go +++ b/featureflag/global.go @@ -1,27 +1,27 @@ package featureflag import ( - "sync" - "github.com/sirupsen/logrus" + "go.uber.org/atomic" + "unsafe" ) -var globalLock sync.Mutex -var globalClient Client = MockClient{} +// See https://blog.dubbelboer.com/2015/08/23/rwmutex-vs-atomicvalue-vs-unsafepointer.html +var ( + defaultClient Client = MockClient{} + globalClient = atomic.NewUnsafePointer(unsafe.Pointer(&defaultClient)) +) func SetGlobalClient(client Client) { if client == nil { return } - globalLock.Lock() - globalClient = client - globalLock.Unlock() + globalClient.Store(unsafe.Pointer(&client)) } func GetGlobalClient() Client { - globalLock.Lock() - defer globalLock.Unlock() - return globalClient + c := (*Client)(globalClient.Load()) + return *c } // Init will initialize global client with a launch darkly client diff --git a/featureflag/global_test.go b/featureflag/global_test.go new file mode 100644 index 0000000..e664158 --- /dev/null +++ b/featureflag/global_test.go @@ -0,0 +1,16 @@ +package featureflag + +import ( + "github.com/stretchr/testify/require" + "testing" +) + +func TestGlobalAccess(t *testing.T) { + // initial value should be default + require.Equal(t, defaultClient, GetGlobalClient()) + + // setting new global should be reflected + n := &ldClient{} + SetGlobalClient(n) + require.Equal(t, n, GetGlobalClient()) +} diff --git a/go.mod b/go.mod index 5d7f493..059a247 100644 --- a/go.mod +++ b/go.mod @@ -36,6 +36,7 @@ require ( github.com/tidwall/pretty v1.0.1 // indirect github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c // indirect go.mongodb.org/mongo-driver v1.9.0 + go.uber.org/atomic v1.9.0 golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc gopkg.in/DataDog/dd-trace-go.v1 v1.34.0 gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect diff --git a/go.sum b/go.sum index 78c1b82..93a454b 100644 --- a/go.sum +++ b/go.sum @@ -389,6 +389,8 @@ go.mongodb.org/mongo-driver v1.9.0/go.mod h1:0sQWfOeY63QTntERDJJ/0SuKK0T1uVSgKCu go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=