Skip to content

Commit

Permalink
1 to n support and eventing completeness
Browse files Browse the repository at this point in the history
Signed-off-by: Kavindu Dodanduwa <[email protected]>
  • Loading branch information
Kavindu-Dodan committed Jun 30, 2023
1 parent 295a4eb commit c847651
Show file tree
Hide file tree
Showing 10 changed files with 1,119 additions and 165 deletions.
3 changes: 1 addition & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ require (
github.com/golang/mock v1.6.0
github.com/open-feature/go-sdk-contrib/providers/flagd v0.1.7
github.com/open-feature/go-sdk-contrib/tests/flagd v1.1.0
golang.org/x/sync v0.1.0
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1
golang.org/x/text v0.10.0
)

Expand Down Expand Up @@ -47,7 +47,6 @@ require (
go.uber.org/atomic v1.10.0 // indirect
go.uber.org/multierr v1.8.0 // indirect
go.uber.org/zap v1.24.0 // indirect
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect
golang.org/x/net v0.6.0 // indirect
golang.org/x/sys v0.5.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect
Expand Down
2 changes: 0 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -388,8 +388,6 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
Expand Down
80 changes: 60 additions & 20 deletions pkg/openfeature/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/go-logr/logr"
"github.com/open-feature/go-sdk/pkg/openfeature/internal"
"golang.org/x/exp/maps"
)

// evaluationAPI wraps OpenFeature evaluation API functionalities
Expand All @@ -16,7 +17,7 @@ type evaluationAPI struct {
evalCtx EvaluationContext
logger logr.Logger
mu sync.RWMutex
eventExecutor
eventExecutor *eventExecutor
}

// newEvaluationAPI is a helper to generate an API. Used internally
Expand Down Expand Up @@ -46,10 +47,10 @@ func (api *evaluationAPI) setProvider(provider FeatureProvider) error {
// Initialize new default provider and shutdown the old one
// Provider update must be non-blocking, hence initialization & shutdown happens concurrently
oldProvider := api.defaultProvider
api.initAndShutdown(provider, oldProvider)
api.defaultProvider = provider

err := api.registerDefaultProvider(provider)
api.initNewAndShutdownOld(provider, oldProvider)
err := api.eventExecutor.registerDefaultProvider(provider)
if err != nil {
return err
}
Expand All @@ -76,10 +77,11 @@ func (api *evaluationAPI) setNamedProvider(clientName string, provider FeaturePr

// Initialize new default provider and shutdown the old one
// Provider update must be non-blocking, hence initialization & shutdown happens concurrently
api.initAndShutdown(provider, api.namedProviders[clientName])
oldProvider := api.namedProviders[clientName]
api.namedProviders[clientName] = provider

err := api.registerNamedEventingProvider(clientName, provider)
api.initNewAndShutdownOld(provider, oldProvider)
err := api.eventExecutor.registerNamedEventingProvider(clientName, provider)
if err != nil {
return err
}
Expand Down Expand Up @@ -125,6 +127,9 @@ func (api *evaluationAPI) addHooks(hooks ...Hook) {
}

func (api *evaluationAPI) shutdown() {
api.mu.Lock()
defer api.mu.Unlock()

v, ok := api.defaultProvider.(StateHandler)
if ok {
v.Shutdown()
Expand Down Expand Up @@ -161,21 +166,56 @@ func (api *evaluationAPI) forTransaction(clientName string) (FeatureProvider, []
return provider, api.hks, api.evalCtx
}

// initAndShutdown is a helper to initialise new FeatureProvider and shutdown old FeatureProvider.
// Operation happens concurrently.
func (api *evaluationAPI) initAndShutdown(newProvider FeatureProvider, oldProvider FeatureProvider) {
go func() {
v, ok := newProvider.(StateHandler)
if ok {
v.Init(api.evalCtx)
}

// oldProvider can be nil
if oldProvider != nil {
v, ok = oldProvider.(StateHandler)
if ok {
v.Shutdown()
// initNewAndShutdownOld is a helper to initialise new FeatureProvider and shutdown the old FeatureProvider.
// Operations happen concurrently.
func (api *evaluationAPI) initNewAndShutdownOld(newProvider FeatureProvider, oldProvider FeatureProvider) {
v, ok := newProvider.(StateHandler)
if ok && v.Status() == NotReadyState {
go func(provider FeatureProvider, stateHandler StateHandler, evalCtx EvaluationContext, eventChan chan eventPayload) {
err := stateHandler.Init(evalCtx)
if err != nil {
eventChan <- eventPayload{
Event{
ProviderName: provider.Metadata().Name,
EventType: ProviderError,
ProviderEventDetails: ProviderEventDetails{},
}, provider,
}
} else {
eventChan <- eventPayload{
Event{
ProviderName: provider.Metadata().Name,
EventType: ProviderReady,
ProviderEventDetails: ProviderEventDetails{},
}, provider,
}
}
}(newProvider, v, api.evalCtx, api.eventExecutor.eventChan)
}

v, ok = oldProvider.(StateHandler)

// oldProvider can be nil or without state handling capability
if oldProvider == nil || !ok {
return
}

// check for multiple bindings
if oldProvider == api.defaultProvider || contains(oldProvider, maps.Values(api.namedProviders)) {
return
}

go func(forShutdown StateHandler) {
forShutdown.Shutdown()
}(v)
}

func contains(provider FeatureProvider, in []FeatureProvider) bool {
for _, p := range in {
if provider == p {
return true
}
}()
}

return false
}
Loading

0 comments on commit c847651

Please sign in to comment.