-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add
MetaProvider
gem and basic implementation (#17)
Signed-off-by: Max VelDink <mveldink@justworks.com> Signed-off-by: Alexandre Chakroun <alexandre.chakroun@doctolib.com> Co-authored-by: Alexandre Chakroun <11556013+alxckn@users.noreply.github.com>
- Loading branch information
1 parent
80d6d02
commit 61b8c10
Showing
18 changed files
with
514 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
/.bundle/ | ||
/.yardoc | ||
/_yardoc/ | ||
/coverage/ | ||
/doc/ | ||
/pkg/ | ||
/spec/reports/ | ||
/tmp/ | ||
|
||
# rspec failure tracking | ||
.rspec_status | ||
spec/examples.txt |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
-I lib | ||
--format documentation | ||
--color | ||
--require spec_helper |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
3.3.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
parallel: true | ||
format: progress | ||
ruby_version: 3.1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
ruby 3.3.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# frozen_string_literal: true | ||
|
||
source "https://rubygems.org" | ||
|
||
# Specify your gem's dependencies in openfeature-sdk-meta_provider.gemspec | ||
gemspec |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
PATH | ||
remote: . | ||
specs: | ||
openfeature-sdk-meta_provider (0.1.0) | ||
openfeature-sdk (~> 0.3.0) | ||
|
||
GEM | ||
remote: https://rubygems.org/ | ||
specs: | ||
ast (2.4.2) | ||
debug (1.9.2) | ||
irb (~> 1.10) | ||
reline (>= 0.3.8) | ||
diff-lcs (1.5.1) | ||
io-console (0.7.2) | ||
irb (1.12.0) | ||
rdoc | ||
reline (>= 0.4.2) | ||
json (2.7.2) | ||
language_server-protocol (3.17.0.3) | ||
lint_roller (1.1.0) | ||
openfeature-sdk (0.3.0) | ||
parallel (1.24.0) | ||
parser (3.3.0.5) | ||
ast (~> 2.4.1) | ||
racc | ||
psych (5.1.2) | ||
stringio | ||
racc (1.7.3) | ||
rainbow (3.1.1) | ||
rake (13.2.1) | ||
rdoc (6.6.3.1) | ||
psych (>= 4.0.0) | ||
regexp_parser (2.9.0) | ||
reline (0.5.0) | ||
io-console (~> 0.5) | ||
rexml (3.2.6) | ||
rspec (3.13.0) | ||
rspec-core (~> 3.13.0) | ||
rspec-expectations (~> 3.13.0) | ||
rspec-mocks (~> 3.13.0) | ||
rspec-core (3.13.0) | ||
rspec-support (~> 3.13.0) | ||
rspec-expectations (3.13.0) | ||
diff-lcs (>= 1.2.0, < 2.0) | ||
rspec-support (~> 3.13.0) | ||
rspec-mocks (3.13.0) | ||
diff-lcs (>= 1.2.0, < 2.0) | ||
rspec-support (~> 3.13.0) | ||
rspec-support (3.13.1) | ||
rubocop (1.62.1) | ||
json (~> 2.3) | ||
language_server-protocol (>= 3.17.0) | ||
parallel (~> 1.10) | ||
parser (>= 3.3.0.2) | ||
rainbow (>= 2.2.2, < 4.0) | ||
regexp_parser (>= 1.8, < 3.0) | ||
rexml (>= 3.2.5, < 4.0) | ||
rubocop-ast (>= 1.31.1, < 2.0) | ||
ruby-progressbar (~> 1.7) | ||
unicode-display_width (>= 2.4.0, < 3.0) | ||
rubocop-ast (1.31.2) | ||
parser (>= 3.3.0.4) | ||
rubocop-performance (1.20.2) | ||
rubocop (>= 1.48.1, < 2.0) | ||
rubocop-ast (>= 1.30.0, < 2.0) | ||
ruby-progressbar (1.13.0) | ||
standard (1.35.1) | ||
language_server-protocol (~> 3.17.0.2) | ||
lint_roller (~> 1.0) | ||
rubocop (~> 1.62.0) | ||
standard-custom (~> 1.0.0) | ||
standard-performance (~> 1.3) | ||
standard-custom (1.0.2) | ||
lint_roller (~> 1.0) | ||
rubocop (~> 1.50) | ||
standard-performance (1.3.1) | ||
lint_roller (~> 1.1) | ||
rubocop-performance (~> 1.20.2) | ||
stringio (3.1.0) | ||
unicode-display_width (2.5.0) | ||
|
||
PLATFORMS | ||
arm64-darwin-23 | ||
ruby | ||
|
||
DEPENDENCIES | ||
debug (~> 1.9.2) | ||
openfeature-sdk-meta_provider! | ||
rake (~> 13.0) | ||
rspec (~> 3.12) | ||
standard (~> 1.34) | ||
|
||
BUNDLED WITH | ||
2.5.6 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
# OpenFeature::SDK::Provider::MetaProvider for Ruby | ||
|
||
The `OpenFeature::SDK::Provider::MetaProvider` is a utility provider implementation that takes multiple [providers](https://docs.openfeature.dev/docs/specification/sections/providers) for use during flag resolution. This can be helpful when an organization is migrating or consolidating feature flag providers as they transition to OpenFeature. There are usually a combination of internal and vendor providers that are combined together to handle flag resolution. If your organization has different providers for different teams, consider looking at using [domains](https://openfeature.dev/specification/glossary#domain). | ||
|
||
## Installation | ||
|
||
Coming soon! | ||
|
||
## Usage | ||
|
||
The `MetaProvider` is initialized with a collection of `Provider`s and a strategy for fetching flags from them. | ||
|
||
```ruby | ||
# Create a MetaProvider | ||
meta_provider = OpenFeature::SDK::Provider::MetaProvider.new( | ||
providers: [ | ||
OpenFeature::SDK::ProviderInMemoryProvider.new, | ||
MyCustomProvider.new | ||
], | ||
strategy: :first_match | ||
) | ||
|
||
# Use it as the default provider | ||
OpenFeature.configure do |c| | ||
c.set_provider(meta_provider) | ||
end | ||
``` | ||
|
||
### Strategies | ||
|
||
#### :first_match | ||
|
||
When `:first_match` is given as the strategy, each provider will be evaluated, in the order they were passed in, for the requested `flag_key`. The first provider where the `flag_key` is found will be returned, short-circuiting flag evaluation with the remaining providers. In the case of a provider error, or no matching flags, returns the default value. | ||
|
||
|
||
## Contributing | ||
|
||
https://github.com/open-feature/ruby-sdk-contrib |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# frozen_string_literal: true | ||
|
||
require "bundler/gem_tasks" | ||
require "rspec/core/rake_task" | ||
|
||
RSpec::Core::RakeTask.new(:spec) | ||
|
||
require "standard/rake" | ||
|
||
task default: %i[standard spec] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
#!/usr/bin/env ruby | ||
# frozen_string_literal: true | ||
|
||
require "bundler/setup" | ||
require "open_feature/sdk/provider/meta_provider" | ||
|
||
# You can add fixtures and/or initialization code here to make experimenting | ||
# with your gem easier. You can also use a different console, if you like. | ||
|
||
# (If you use this, don't forget to add pry to your Gemfile!) | ||
# require "pry" | ||
# Pry.start | ||
|
||
require "irb" | ||
IRB.start(__FILE__) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
#!/usr/bin/env ruby | ||
# frozen_string_literal: true | ||
|
||
# | ||
# This file was generated by Bundler. | ||
# | ||
# The application 'rake' is installed as part of a gem, and | ||
# this file is here to facilitate running it. | ||
# | ||
|
||
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) | ||
|
||
bundle_binstub = File.expand_path("bundle", __dir__) | ||
|
||
if File.file?(bundle_binstub) | ||
if File.read(bundle_binstub, 300).include?("This file was generated by Bundler") | ||
load(bundle_binstub) | ||
else | ||
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run. | ||
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.") | ||
end | ||
end | ||
|
||
require "rubygems" | ||
require "bundler/setup" | ||
|
||
load Gem.bin_path("rake", "rake") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
#!/usr/bin/env bash | ||
set -euo pipefail | ||
IFS=$'\n\t' | ||
set -vx | ||
|
||
bundle install | ||
|
||
# Do any other automated setup that you need to do here |
79 changes: 79 additions & 0 deletions
79
providers/openfeature-sdk-meta_provider/lib/open_feature/sdk/provider/meta_provider.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
# frozen_string_literal: true | ||
|
||
module OpenFeature | ||
module SDK | ||
module Provider | ||
# Used to pull from multiple providers. | ||
class MetaProvider | ||
# @param providers [Array<Provider>] | ||
# @param strategy [Symbol] When `:first_match`, returns first matched resolution. Providers will be searched | ||
# in the order they were given. Defaults to `:first_match`. | ||
def initialize(providers:, strategy: :first_match) | ||
@providers = providers | ||
@strategy = strategy | ||
end | ||
|
||
def metadata | ||
ProviderMetadata.new(name: "MetaProvider: #{providers.map { |provider| provider.metadata.name }.join(", ")}") | ||
end | ||
|
||
def init | ||
providers.each { |provider| provider.init } | ||
end | ||
|
||
def shutdown | ||
providers.each(&:shutdown) | ||
end | ||
|
||
def fetch_boolean_value(flag_key:, default_value:, evaluation_context: nil) | ||
fetch_from_sources(default_value:) do |provider| | ||
provider.fetch_boolean_value(flag_key:, default_value:, evaluation_context:) | ||
end | ||
end | ||
|
||
def fetch_number_value(flag_key:, default_value:, evaluation_context: nil) | ||
fetch_from_sources(default_value:) do |provider| | ||
provider.fetch_number_value(flag_key:, default_value:, evaluation_context:) | ||
end | ||
end | ||
|
||
def fetch_object_value(flag_key:, default_value:, evaluation_context: nil) | ||
fetch_from_sources(default_value:) do |provider| | ||
provider.fetch_object_value(flag_key:, default_value:, evaluation_context:) | ||
end | ||
end | ||
|
||
def fetch_string_value(flag_key:, default_value:, evaluation_context: nil) | ||
fetch_from_sources(default_value:) do |provider| | ||
provider.fetch_string_value(flag_key:, default_value:, evaluation_context:) | ||
end | ||
end | ||
|
||
private | ||
|
||
attr_reader :providers, :strategy | ||
|
||
def fetch_from_sources(default_value:, &blk) | ||
case strategy | ||
when :first_match | ||
successful_details = providers.each do |provider| | ||
details = yield(provider) | ||
|
||
break details if details.error_code.nil? | ||
rescue | ||
next | ||
end | ||
|
||
if successful_details.is_a?(ResolutionDetails) | ||
successful_details | ||
else | ||
ResolutionDetails.new(value: default_value, error_code: ErrorCode::GENERAL, reason: Reason::ERROR) | ||
end | ||
else | ||
ResolutionDetails.new(value: default_value, error_code: ErrorCode::GENERAL, reason: "Unknown strategy for MetaProvider") | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
36 changes: 36 additions & 0 deletions
36
providers/openfeature-sdk-meta_provider/openfeature-sdk-meta_provider.gemspec
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
# frozen_string_literal: true | ||
|
||
Gem::Specification.new do |spec| | ||
spec.name = "openfeature-sdk-meta_provider" | ||
spec.version = "0.1.0" | ||
spec.authors = ["OpenFeature Authors"] | ||
spec.email = ["cncf-openfeature-contributors@lists.cncf.io"] | ||
|
||
spec.summary = "Meta provider for the OpenFeature Ruby SDK" | ||
spec.description = "The MetaProvider wraps multiple other providers and uses a given strategy to resolve flags using all of them." | ||
spec.homepage = "https://github.com/open-feature/ruby-sdk-contrib/providers/openfeature-sdk-meta_provider" | ||
spec.license = "Apache-2.0" | ||
spec.required_ruby_version = ">= 3.1" | ||
|
||
spec.metadata["homepage_uri"] = spec.homepage | ||
spec.metadata["source_code_uri"] = "https://github.com/open-feature/ruby-sdk-contrib/providers/openfeature-sdk-meta_provider" | ||
spec.metadata["changelog_uri"] = "https://github.com/open-feature/ruby-sdk-contrib/blob/main/CHANGELOG.md" | ||
spec.metadata["bug_tracker_uri"] = "https://github.com/open-feature/ruby-sdk-contrib/issues" | ||
spec.metadata["documentation_uri"] = "https://github.com/open-feature/ruby-sdk-contrib/README.md" | ||
|
||
# Specify which files should be added to the gem when it is released. | ||
# The `git ls-files -z` loads the files in the RubyGem that have been added into git. | ||
spec.files = Dir.chdir(File.expand_path(__dir__)) do | ||
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } | ||
end | ||
spec.bindir = "exe" | ||
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } | ||
spec.require_paths = ["lib"] | ||
|
||
spec.add_dependency "openfeature-sdk", "~> 0.3.0" | ||
|
||
spec.add_development_dependency "rake", "~> 13.0" | ||
spec.add_development_dependency "rspec", "~> 3.12" | ||
spec.add_development_dependency "standard", "~> 1.34" | ||
spec.add_development_dependency "debug", "~> 1.9.2" | ||
end |
Oops, something went wrong.