Skip to content

Commit

Permalink
feat!: Implement Requirement 1.1.3 (#80)
Browse files Browse the repository at this point in the history
Signed-off-by: Max VelDink <[email protected]>
  • Loading branch information
maxveldink authored Mar 9, 2024
1 parent 25680a4 commit bc65e7a
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 26 deletions.
16 changes: 9 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,15 @@ require 'json' # For JSON.dump
# API Initialization and configuration

OpenFeature::SDK.configure do |config|
# your provider of choice
config.provider = OpenFeature::SDK::Provider::InMemoryProvider.new(
{
"flag1" => true,
"flag2" => 1
}
)
# your provider of choice, which will be used as the default provider
config.set_provider(OpenFeature::SDK::Provider::InMemoryProvider.new(
{
"flag1" => true,
"flag2" => 1
}
))
# alternatively, you can bind multiple providers to different domains
config.set_provider(OpenFeature::SDK::Provider::NoOpProvider.new, domain: "legacy_flags")
end

# Create a client
Expand Down
4 changes: 2 additions & 2 deletions lib/open_feature/sdk/api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ module SDK
# To use the SDK, you can optionally configure a <tt>Provider</tt>, with <tt>Hook</tt>
#
# OpenFeature::SDK::API.instance.configure do |config|
# config.provider = NoOpProvider.new
# config.set_provider NoOpProvider.new
# end
#
# If no provider is specified, the <tt>NoOpProvider</tt> is set as the default <tt>Provider</tt>.
Expand All @@ -30,7 +30,7 @@ class API
include Singleton # Satisfies Flag Evaluation API Requirement 1.1.1
extend Forwardable

def_delegators :configuration, :provider, :provider=, :hooks, :context
def_delegators :configuration, :provider, :set_provider, :hooks, :context

def configuration
@configuration ||= Configuration.new
Expand Down
14 changes: 9 additions & 5 deletions lib/open_feature/sdk/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,28 @@ class Configuration
extend Forwardable

attr_accessor :context, :hooks
attr_reader :provider

def_delegator :@provider, :metadata
def_delegator :provider, :metadata

def initialize
@hooks = []
@providers = {}
end

def provider(domain: nil)
@providers[domain]
end

# When switching providers, there are a few lifecycle methods that need to be taken care of.
# 1. If a provider is already set, we need to call `shutdown` on it.
# 2. On the new provider, call `init`.
# 3. Finally, set the internal provider to the new provider
def provider=(provider)
@provider.shutdown if @provider.respond_to?(:shutdown)
def set_provider(provider, domain: nil)
@providers[domain].shutdown if @providers[domain].respond_to?(:shutdown)

provider.init if provider.respond_to?(:init)

@provider = provider
@providers[domain] = provider
end
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/open_feature/sdk/provider/no_op_provider.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ module Provider
# To use <tt>NoOpProvider</tt>, it can be set during the configuration of the SDK
#
# OpenFeature::SDK.configure do |config|
# config.provider = NoOpProvider.new
# config.set_provider NoOpProvider.new
# end
#
# Within the <tt>NoOpProvider</tt>, the following methods exist
Expand Down
6 changes: 3 additions & 3 deletions spec/open_feature/sdk/api_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
context "with Requirement 1.1.3" do
before do
api.configure do |config|
config.provider = OpenFeature::SDK::Provider::NoOpProvider.new
config.set_provider(OpenFeature::SDK::Provider::NoOpProvider.new)
config.hooks << hook1
config.hooks << hook2
end
Expand All @@ -28,7 +28,7 @@
context "with Requirement 1.1.4" do
before do
api.configure do |config|
config.provider = OpenFeature::SDK::Provider::NoOpProvider.new
config.set_provider(OpenFeature::SDK::Provider::NoOpProvider.new)
end
end

Expand All @@ -52,7 +52,7 @@
context "with Requirement 1.1.5" do
before do
api.configure do |config|
config.provider = OpenFeature::SDK::Provider::NoOpProvider.new
config.set_provider(OpenFeature::SDK::Provider::NoOpProvider.new)
end

api.build_client(name: "requirement-1.1.5")
Expand Down
19 changes: 15 additions & 4 deletions spec/open_feature/sdk/configuration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,38 @@
RSpec.describe OpenFeature::SDK::Configuration do
subject(:configuration) { described_class.new }

describe "#provider=" do
describe "#set_provider" do
context "when provider has an init method" do
let(:provider) { OpenFeature::SDK::Provider::InMemoryProvider.new }

it "inits and sets the provider" do
expect(provider).to receive(:init)

configuration.provider = provider
configuration.set_provider(provider)

expect(configuration.provider).to be(provider)
end
end

context "when provider does not have an init method" do
it "sets the provider" do
it "sets the default provider" do
provider = OpenFeature::SDK::Provider::NoOpProvider.new

configuration.provider = provider
configuration.set_provider(provider)

expect(configuration.provider).to be(provider)
end
end

context "when name is given" do
it "binds the provider to that name" do
provider = OpenFeature::SDK::Provider::InMemoryProvider.new
expect(provider).to receive(:init)

configuration.set_provider(provider, domain: "testing")

expect(configuration.provider(domain: "testing")).to be(provider)
end
end
end
end
32 changes: 28 additions & 4 deletions spec/specification/flag_evaluation_api_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
specify "the API must define a provider mutator" do
provider = OpenFeature::SDK::Provider::NoOpProvider.new

OpenFeature::SDK.provider = provider
OpenFeature::SDK.set_provider(provider)

expect(OpenFeature::SDK.provider).to be(provider)
end
Expand All @@ -25,7 +25,7 @@
provider = OpenFeature::SDK::Provider::InMemoryProvider.new
expect(provider).to receive(:init)

OpenFeature::SDK.provider = provider
OpenFeature::SDK.set_provider(provider)
end
end

Expand All @@ -37,8 +37,32 @@
expect(previous_provider).to receive(:shutdown)
expect(new_provider).not_to receive(:shutdown)

OpenFeature::SDK.provider = previous_provider
OpenFeature::SDK.provider = new_provider
OpenFeature::SDK.set_provider(previous_provider)
OpenFeature::SDK.set_provider(new_provider)
end
end

context "Requirement 1.1.3" do
specify "the API must provide a function to bind a given provider to one or more client names" do
first_provider = OpenFeature::SDK::Provider::InMemoryProvider.new
second_provider = OpenFeature::SDK::Provider::InMemoryProvider.new

OpenFeature::SDK.set_provider(first_provider, domain: "first")
OpenFeature::SDK.set_provider(second_provider, domain: "second")

expect(OpenFeature::SDK.provider(domain: "first")).to be(first_provider)
expect(OpenFeature::SDK.provider(domain: "second")).to be(second_provider)
end

specify "if client name is already bound, it is overwritten" do
previous_provider = OpenFeature::SDK::Provider::InMemoryProvider.new
new_provider = OpenFeature::SDK::Provider::InMemoryProvider.new

OpenFeature::SDK.set_provider(previous_provider, domain: "testing")
expect(OpenFeature::SDK.provider(domain: "testing")).to be(previous_provider)

OpenFeature::SDK.set_provider(new_provider, domain: "testing")
expect(OpenFeature::SDK.provider(domain: "testing")).to be(new_provider)
end
end
end
Expand Down

0 comments on commit bc65e7a

Please sign in to comment.