Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
c6249d4
feat(multi-provider): set up multi-provider directory
bbland1 Feb 21, 2025
446b543
feat: set up func to create new multiprovider & register passed provi…
bbland1 Feb 22, 2025
1fae6f0
feat: added Metadata Method to the multiprovider
bbland1 Feb 22, 2025
aeb8bd3
feat: added the based of the Init method that will process the inital…
bbland1 Feb 25, 2025
0605d94
moved providers into pkg directory
bbland1 Feb 26, 2025
51c33bc
added Init method to handle any providers with intialization
bbland1 Feb 27, 2025
1d7eed5
added the Shutdown method
bbland1 Feb 27, 2025
9ddd19b
added getter methods to the unexported fields
bbland1 Feb 28, 2025
09a988f
added tests to check unique name for providers passed
bbland1 Feb 28, 2025
7df8cba
added test checking if error thrown for unique name if not unique
bbland1 Mar 1, 2025
dcbc5d7
added test to check for metadata, currently fails
bbland1 Mar 4, 2025
f06e745
added test for getter methods of the struct provider entries
bbland1 Mar 5, 2025
676bcee
added test for MP Init method with mock providers that have Init methods
bbland1 Mar 7, 2025
4634789
added shutdown test confirming method run in MP when called
bbland1 Mar 7, 2025
af13736
added the empty bases of the evaluations and hooks methods
bbland1 Mar 9, 2025
fcc1f7c
added test for init errors by a provider and reduced the mock provide…
bbland1 Mar 9, 2025
dc539b9
removed memprovider since NewTestProvider uses it
bbland1 Mar 9, 2025
2b926df
added metadata aggregate to the method and updated test to properly use
bbland1 Mar 9, 2025
b0f777d
added ready and error state to the init method for the multi provider
bbland1 Apr 7, 2025
89f1f8d
added a func to determine which eval strategy to use and added it to …
bbland1 Apr 9, 2025
10b8d74
creating the base of a base strategy similar to js version that can b…
bbland1 Apr 10, 2025
c5f5f14
fleshing out the BaseStrategy to have the help funcs to be used in st…
bbland1 Apr 10, 2025
ecb7170
feat: Define strategy interface & strategy name type
jblacker Apr 7, 2025
e0cc5ad
feat: Add FirstSuccessStrategy Implementation
jblacker Apr 9, 2025
af79893
doc: Add README for multiprovider
jblacker Apr 16, 2025
542e5d2
feat: Configure strategy in provider initializer
jblacker Apr 16, 2025
8c78f3e
feat: wire it all up
jblacker Apr 16, 2025
aa2a0d1
refactor: use strategy's own name
jblacker Apr 16, 2025
ed349d3
fix: handle post-rebase conflicts
jblacker Apr 16, 2025
ef2514c
refactor: Rename types, reorganize package structure
jblacker Apr 19, 2025
b0b627e
doc: Update README
jblacker Apr 19, 2025
faa8a38
cleanup: Remove unused public strategy package
jblacker Apr 19, 2025
4f6ccb7
fix: correct test names for first_success_test
jblacker Apr 19, 2025
44d6663
feat: implement comparison strategy
jblacker Apr 19, 2025
9edebd1
fix: Patch bug where metadata would not be generated in a stable way
jblacker Apr 22, 2025
6ca60ed
refactor: Move options to new file
jblacker Apr 23, 2025
bdb4a39
refactor: Rewrite aggregate errors & simplify Init method
jblacker Apr 23, 2025
a743757
fix: Correct broken cleanErrorMessage helper func
jblacker Apr 23, 2025
41d8247
feat: Add tag merge helper method
jblacker Apr 23, 2025
35f3214
refactor: Move mock file to mocks package
jblacker Apr 23, 2025
66fd619
refactor: Rewrite first success implementation to be more go-y
jblacker Apr 23, 2025
4cab3c9
fix: correct bug in default resolution func
jblacker Apr 23, 2025
67306b4
refactor: Use evaluator for first_match
jblacker Apr 23, 2025
7248cf8
refactor: Rename test helper
jblacker Apr 23, 2025
9228c94
refactor: Alias package to prevent shadowing
jblacker Apr 23, 2025
19ccefe
refactor: Modify comparison implementation with comp functions
jblacker Apr 24, 2025
649078f
doc: Update README
jblacker Apr 24, 2025
4414d9d
fix: Remove duplicated error type
jblacker Apr 24, 2025
366e669
fix: Add missing imports to strategies due to merge resolution issues
jblacker Apr 24, 2025
d52aa41
fix: Patch bug related to extracting providers from MultiProvider struct
jblacker Apr 24, 2025
4415ee3
cleanup: Remove unused components from provider tests
jblacker Apr 24, 2025
02aa953
fix: Correct bug related to FirstStrategy error handling (not flag no…
jblacker Apr 24, 2025
e60c3ac
fix: Correct default result build
jblacker Apr 24, 2025
72ab3a6
fix: Handle flag not found separately from error for FirstSuccess str…
jblacker Apr 24, 2025
03836c7
fix: Move strategies outside of internal
jblacker Apr 24, 2025
72bc105
feat: Add Makefile
jblacker Apr 24, 2025
87fdedb
chore: generate mocks
jblacker Apr 24, 2025
0c4306c
fix: Correct mock generation & regenerate
jblacker Apr 24, 2025
f953aac
feat: Add support for custom strategies
jblacker Apr 24, 2025
6c43c6b
doc: document options
jblacker Apr 24, 2025
11daf4f
doc: Document public methods in providers.go
jblacker Apr 24, 2025
74f5ad1
refactor: downgrade go-sdk
jblacker Apr 25, 2025
3c3abc7
chore: go mod tidy
jblacker Apr 25, 2025
8846c52
chore: fix makefile & rebuild mocks
jblacker Apr 25, 2025
225a1bc
fix: repair code post downgrade
jblacker Apr 25, 2025
3e092fc
doc: Update documentation
jblacker Apr 25, 2025
71a9f29
refactor: Simplify ProviderMap.Size() impl
jblacker Apr 25, 2025
ac97b25
Merge branch 'main' into 599/implement-multiprovider
jblacker Apr 25, 2025
16a541c
fix: Correct one last broken test post downgrade
jblacker Apr 25, 2025
4ab2651
Merge branch '599/implement-multiprovider' of github.com:jblacker/go-…
jblacker Apr 25, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@
"providers/ofrep": "0.1.5",
"providers/prefab": "0.0.2",
"tests/flagd": "1.4.1",
"providers/go-feature-flag-in-process": "0.1.0"
"providers/go-feature-flag-in-process": "0.1.0",
"providers/multi-provider": "0.0.3"
}
10 changes: 10 additions & 0 deletions providers/multi-provider/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.PHONY: generate test
GOPATH_LOC = ${GOPATH}

generate:
go generate ./...
go mod download
mockgen -source=${GOPATH}/pkg/mod/github.com/open-feature/go-sdk@v1.13.1/openfeature/provider.go -package=mocks -destination=./internal/mocks/provider_mock.go

test:
go test ./...
84 changes: 84 additions & 0 deletions providers/multi-provider/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
OpenFeature Multi-Provider
------------

The Multi-Provider allows you to use multiple underlying providers as sources of flag data for the OpenFeature server SDK.
When a flag is being evaluated, the Multi-Provider will consult each underlying provider it is managing in order to
determine the final result. Different evaluation strategies can be defined to control which providers get evaluated and
which result is used.

The Multi-Provider is a powerful tool for performing migrations between flag providers, or combining multiple providers
into a single feature flagging interface. For example:

- **Migration**: When migrating between two providers, you can run both in parallel under a unified flagging interface.
As flags are added to the new provider, the Multi-Provider will automatically find and return them, falling back to the old provider
if the new provider does not have
- **Multiple Data Sources**: The Multi-Provider allows you to seamlessly combine many sources of flagging data, such as
environment variables, local files, database values and SaaS hosted feature management systems.

# Installation

```sh
go get github.com/open-feature/go-sdk-contrib/providers/multi-provider
go get github.com/open-feature/go-sdk
```

# Usage

```go
import (
"github.com/open-feature/go-sdk/openfeature"
mp "github.com/open-feature/go-sdk-contrib/providers/multi-provider"
)

providers := make(mp.ProviderMap)
providers["providerA"] = providerA
providers["providerB"] = providerB
provider, err := mp.NewMultiProvider(providers, mp.StrategyFirstMatch, WithLogger(myLogger))
openfeature.SetProvider(provider)
```

# Options

- `WithTimeout` - the duration is used for the total timeout across parallel operations. If none is set it will default
to 5 seconds. This is not supported for `FirstMatch` yet, which executes sequentially
- `WithFallbackProvider` - Used for setting a fallback provider for the `Comparison` strategy
- `WithLogger` - Provides slog support

# Strategies

There are multiple strategies that can be used to determine the result returned to the caller. A strategy must be set at
initialization time.

There are 3 strategies available currently:

- _First Match_
- _First Success_
- _Comparison_

## First Match Strategy

The first match strategy works by **sequentially** calling each provider in the order that they are provided to the mutli-provider.
The first provider that returns a result. It will try calling the next provider whenever it encounters a `FLAG_NOT_FOUND`
error. However, if a provider returns an error other than `FLAG_NOT_FOUND` the provider will stop and return the default
value along with setting the error details if a detailed request is issued. (allow changing this behavior?)

## First Success Strategy

The First Success strategy works by calling each provider in **parallel**. The first provider that returns a response
with no errors is returned and all other calls are cancelled. If no provider provides a successful result the default
value will be returned to the caller.

## Comparison

The Comparison strategy works by calling each provider in **parallel**. All results are collected from each provider and
then the resolved results are compared to each other. If they all agree then that value is returned. If not and a fallback
provider is specified then the fallback will be executed. If no fallback is configured then the default value will be
returned. If a provider returns `FLAG_NOT_FOUND` that is not included in the comparison. If all providers
return not found then the default value is returned. Finally, if any provider returns an error other than `FLAG_NOT_FOUND`
the evaluation immediately stops and that error result is returned. This strategy does NOT support `ObjectEvaluation`

# Not Yet Implemented

- Hooks support
- Event support
- Full slog support
18 changes: 18 additions & 0 deletions providers/multi-provider/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module github.com/open-feature/go-sdk-contrib/providers/multi-provider

go 1.23.0

require (
github.com/open-feature/go-sdk v1.13.1
github.com/stretchr/testify v1.9.0
go.uber.org/mock v0.5.1
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842
golang.org/x/sync v0.7.0
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
24 changes: 24 additions & 0 deletions providers/multi-provider/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/open-feature/go-sdk v1.13.1 h1:RJbS70eyi7Jd3Zm5bFnaahNKNDXn+RAVnctpGu+uPis=
github.com/open-feature/go-sdk v1.13.1/go.mod h1:O8r4mhgeRIsjJ0ZBXlnE0BtbT/79W44gQceR7K8KYgo=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
go.uber.org/mock v0.5.1 h1:ASgazW/qBmR+A32MYFDB6E2POoTgOwT509VP0CT/fjs=
go.uber.org/mock v0.5.1/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM=
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
242 changes: 242 additions & 0 deletions providers/multi-provider/internal/mocks/provider_mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading