Skip to content

Commit bc65e7a

Browse files
authored
feat!: Implement Requirement 1.1.3 (#80)
Signed-off-by: Max VelDink <maxveldink@gmail.com>
1 parent 25680a4 commit bc65e7a

File tree

7 files changed

+67
-26
lines changed

7 files changed

+67
-26
lines changed

README.md

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,15 @@ require 'json' # For JSON.dump
4242
# API Initialization and configuration
4343

4444
OpenFeature::SDK.configure do |config|
45-
# your provider of choice
46-
config.provider = OpenFeature::SDK::Provider::InMemoryProvider.new(
47-
{
48-
"flag1" => true,
49-
"flag2" => 1
50-
}
51-
)
45+
# your provider of choice, which will be used as the default provider
46+
config.set_provider(OpenFeature::SDK::Provider::InMemoryProvider.new(
47+
{
48+
"flag1" => true,
49+
"flag2" => 1
50+
}
51+
))
52+
# alternatively, you can bind multiple providers to different domains
53+
config.set_provider(OpenFeature::SDK::Provider::NoOpProvider.new, domain: "legacy_flags")
5254
end
5355

5456
# Create a client

lib/open_feature/sdk/api.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ module SDK
1919
# To use the SDK, you can optionally configure a <tt>Provider</tt>, with <tt>Hook</tt>
2020
#
2121
# OpenFeature::SDK::API.instance.configure do |config|
22-
# config.provider = NoOpProvider.new
22+
# config.set_provider NoOpProvider.new
2323
# end
2424
#
2525
# If no provider is specified, the <tt>NoOpProvider</tt> is set as the default <tt>Provider</tt>.
@@ -30,7 +30,7 @@ class API
3030
include Singleton # Satisfies Flag Evaluation API Requirement 1.1.1
3131
extend Forwardable
3232

33-
def_delegators :configuration, :provider, :provider=, :hooks, :context
33+
def_delegators :configuration, :provider, :set_provider, :hooks, :context
3434

3535
def configuration
3636
@configuration ||= Configuration.new

lib/open_feature/sdk/configuration.rb

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,28 @@ class Configuration
1414
extend Forwardable
1515

1616
attr_accessor :context, :hooks
17-
attr_reader :provider
1817

19-
def_delegator :@provider, :metadata
18+
def_delegator :provider, :metadata
2019

2120
def initialize
2221
@hooks = []
22+
@providers = {}
23+
end
24+
25+
def provider(domain: nil)
26+
@providers[domain]
2327
end
2428

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

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

34-
@provider = provider
38+
@providers[domain] = provider
3539
end
3640
end
3741
end

lib/open_feature/sdk/provider/no_op_provider.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ module Provider
1111
# To use <tt>NoOpProvider</tt>, it can be set during the configuration of the SDK
1212
#
1313
# OpenFeature::SDK.configure do |config|
14-
# config.provider = NoOpProvider.new
14+
# config.set_provider NoOpProvider.new
1515
# end
1616
#
1717
# Within the <tt>NoOpProvider</tt>, the following methods exist

spec/open_feature/sdk/api_spec.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
context "with Requirement 1.1.3" do
1111
before do
1212
api.configure do |config|
13-
config.provider = OpenFeature::SDK::Provider::NoOpProvider.new
13+
config.set_provider(OpenFeature::SDK::Provider::NoOpProvider.new)
1414
config.hooks << hook1
1515
config.hooks << hook2
1616
end
@@ -28,7 +28,7 @@
2828
context "with Requirement 1.1.4" do
2929
before do
3030
api.configure do |config|
31-
config.provider = OpenFeature::SDK::Provider::NoOpProvider.new
31+
config.set_provider(OpenFeature::SDK::Provider::NoOpProvider.new)
3232
end
3333
end
3434

@@ -52,7 +52,7 @@
5252
context "with Requirement 1.1.5" do
5353
before do
5454
api.configure do |config|
55-
config.provider = OpenFeature::SDK::Provider::NoOpProvider.new
55+
config.set_provider(OpenFeature::SDK::Provider::NoOpProvider.new)
5656
end
5757

5858
api.build_client(name: "requirement-1.1.5")

spec/open_feature/sdk/configuration_spec.rb

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,38 @@
55
RSpec.describe OpenFeature::SDK::Configuration do
66
subject(:configuration) { described_class.new }
77

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

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

15-
configuration.provider = provider
15+
configuration.set_provider(provider)
1616

1717
expect(configuration.provider).to be(provider)
1818
end
1919
end
2020

2121
context "when provider does not have an init method" do
22-
it "sets the provider" do
22+
it "sets the default provider" do
2323
provider = OpenFeature::SDK::Provider::NoOpProvider.new
2424

25-
configuration.provider = provider
25+
configuration.set_provider(provider)
2626

2727
expect(configuration.provider).to be(provider)
2828
end
2929
end
30+
31+
context "when name is given" do
32+
it "binds the provider to that name" do
33+
provider = OpenFeature::SDK::Provider::InMemoryProvider.new
34+
expect(provider).to receive(:init)
35+
36+
configuration.set_provider(provider, domain: "testing")
37+
38+
expect(configuration.provider(domain: "testing")).to be(provider)
39+
end
40+
end
3041
end
3142
end

spec/specification/flag_evaluation_api_spec.rb

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
specify "the API must define a provider mutator" do
1515
provider = OpenFeature::SDK::Provider::NoOpProvider.new
1616

17-
OpenFeature::SDK.provider = provider
17+
OpenFeature::SDK.set_provider(provider)
1818

1919
expect(OpenFeature::SDK.provider).to be(provider)
2020
end
@@ -25,7 +25,7 @@
2525
provider = OpenFeature::SDK::Provider::InMemoryProvider.new
2626
expect(provider).to receive(:init)
2727

28-
OpenFeature::SDK.provider = provider
28+
OpenFeature::SDK.set_provider(provider)
2929
end
3030
end
3131

@@ -37,8 +37,32 @@
3737
expect(previous_provider).to receive(:shutdown)
3838
expect(new_provider).not_to receive(:shutdown)
3939

40-
OpenFeature::SDK.provider = previous_provider
41-
OpenFeature::SDK.provider = new_provider
40+
OpenFeature::SDK.set_provider(previous_provider)
41+
OpenFeature::SDK.set_provider(new_provider)
42+
end
43+
end
44+
45+
context "Requirement 1.1.3" do
46+
specify "the API must provide a function to bind a given provider to one or more client names" do
47+
first_provider = OpenFeature::SDK::Provider::InMemoryProvider.new
48+
second_provider = OpenFeature::SDK::Provider::InMemoryProvider.new
49+
50+
OpenFeature::SDK.set_provider(first_provider, domain: "first")
51+
OpenFeature::SDK.set_provider(second_provider, domain: "second")
52+
53+
expect(OpenFeature::SDK.provider(domain: "first")).to be(first_provider)
54+
expect(OpenFeature::SDK.provider(domain: "second")).to be(second_provider)
55+
end
56+
57+
specify "if client name is already bound, it is overwritten" do
58+
previous_provider = OpenFeature::SDK::Provider::InMemoryProvider.new
59+
new_provider = OpenFeature::SDK::Provider::InMemoryProvider.new
60+
61+
OpenFeature::SDK.set_provider(previous_provider, domain: "testing")
62+
expect(OpenFeature::SDK.provider(domain: "testing")).to be(previous_provider)
63+
64+
OpenFeature::SDK.set_provider(new_provider, domain: "testing")
65+
expect(OpenFeature::SDK.provider(domain: "testing")).to be(new_provider)
4266
end
4367
end
4468
end

0 commit comments

Comments
 (0)