openfeature-sdk-sorbet 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 75df060a41ea89c620620e99d361a57dacbc4ca4df2c28112100ba4020da22e6
4
- data.tar.gz: e0aa5083da80f8f6dc3b47edf67baf6e02a310381743b72ecf86a51005317a82
3
+ metadata.gz: 96650d45be9bb86f0349e27d1ad9d56c748659b3d075b6c2cc6c769fff642571
4
+ data.tar.gz: 370bd63d0ffb1143eec2de19d3b70e5e0b5033b4dcd0f08117dfbaeee7c1f8cd
5
5
  SHA512:
6
- metadata.gz: 52b1805c282d14bdfbb1e79169cce49f4296c8c82b93f0a78288db8d41d5ebd542061c3e66834ea617a14a6555f7247ca7461ee0f70c2560fc173da51ee8922f
7
- data.tar.gz: 2e8c810a78304daf139be9d4b0bebae008a12aeda77ba6d6cb46e646efbb71f543743b93ba40afd675e90058c225c926c91e8a3152b743b9b0860c0b8b96e9fc
6
+ metadata.gz: 915afef5bdae8110b53c4e96dc9494955636753c1170349eb25f432760590fc75004ebd6f8c47bd3359da982b81fbae0c08a7053df4b552fe760f939021bdd00
7
+ data.tar.gz: 799b9745b26bf0eac7cdf5e54b237d63abe8f2af5e238bcaf554bd368105dc880a7cc643e5565529053baa4a7041cbc61a5c95eafcc56331ad25b6c2527883e9
data/.rubocop.yml CHANGED
@@ -19,16 +19,20 @@ Layout/LineLength:
19
19
 
20
20
  Lint/UnusedMethodArgument:
21
21
  Exclude:
22
+ - lib/open_feature/multiple_source_provider.rb
22
23
  - lib/open_feature/no_op_provider.rb
23
24
 
24
25
  Metrics/ClassLength:
25
26
  Exclude:
26
27
  - lib/open_feature/client.rb
27
28
  - test/open_feature/client_test.rb
29
+ - test/open_feature/multiple_source_provider_test.rb
28
30
 
29
31
  Metrics/MethodLength:
30
32
  Exclude:
31
33
  - test/open_feature/evaluation_details_test.rb
34
+ - test/open_feature/multiple_source_provider_test.rb
35
+ - test/support/test_provider.rb
32
36
 
33
37
  Style/AccessorGrouping:
34
38
  Enabled: false
data/CHANGELOG.md CHANGED
@@ -6,6 +6,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.1.2] - 2023-05-16
10
+
11
+ ### Added
12
+
13
+ - Introduced `OpenFeature::MultipleSourceProvider` to allow fetching flags from multiple sources.
14
+
9
15
  ## [0.1.1] - 2023-05-15
10
16
 
11
17
  ### Changed
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- openfeature-sdk-sorbet (0.1.1)
4
+ openfeature-sdk-sorbet (0.1.2)
5
5
  sorbet-runtime (~> 0.5)
6
6
  sorbet-struct-comparable (~> 1.3)
7
7
  zeitwerk (~> 2.6)
@@ -56,14 +56,14 @@ GEM
56
56
  rubocop-sorbet (0.7.0)
57
57
  rubocop (>= 0.90.0)
58
58
  ruby-progressbar (1.13.0)
59
- sorbet (0.5.10826)
60
- sorbet-static (= 0.5.10826)
61
- sorbet-runtime (0.5.10826)
62
- sorbet-static (0.5.10826-universal-darwin-22)
63
- sorbet-static (0.5.10826-x86_64-linux)
64
- sorbet-static-and-runtime (0.5.10826)
65
- sorbet (= 0.5.10826)
66
- sorbet-runtime (= 0.5.10826)
59
+ sorbet (0.5.10827)
60
+ sorbet-static (= 0.5.10827)
61
+ sorbet-runtime (0.5.10827)
62
+ sorbet-static (0.5.10827-universal-darwin-22)
63
+ sorbet-static (0.5.10827-x86_64-linux)
64
+ sorbet-static-and-runtime (0.5.10827)
65
+ sorbet (= 0.5.10827)
66
+ sorbet-runtime (= 0.5.10827)
67
67
  sorbet-struct-comparable (1.3.0)
68
68
  sorbet-runtime (>= 0.5)
69
69
  spoom (1.2.1)
data/README.md CHANGED
@@ -49,6 +49,21 @@ The OpenFeature specification defines [Structure as a potential return type](htt
49
49
 
50
50
  By default, this implementation sets the provider to the `OpenFeature::NoOpProvider` which always returns the default value. It's up to the individual teams to define their own providers based on their flag source (in the future, I'll release open-source providers based on various, common vendors).
51
51
 
52
+ This gem also provides `OpenFeature::MultipleSourceProvider` to allow fetching flags from multiple sources. This is especially useful if your existing application has flags spread across bespoke and vendor solutions and you want to unify the evaluation sites. It can be instantiated and configured like so:
53
+
54
+ ```ruby
55
+ provider = OpenFeature::MultipleSourceProvider.new(
56
+ providers: [
57
+ CustomProvider.new,
58
+ OpenFeature::NoOpProvider.new
59
+ ]
60
+ )
61
+
62
+ OpenFeature.set_provider(provider)
63
+ ```
64
+
65
+ #### Implementing Custom Providers
66
+
52
67
  Thanks to Sorbet interfaces, it's fairly straightforward to implement a new provider. Here is an example for a JSON-based flag format on disk:
53
68
 
54
69
  ```ruby
@@ -0,0 +1,121 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module OpenFeature
5
+ # Used to pull from multiple providers.
6
+ # Order of the providers given to initialize matters.
7
+ # The providers will be evaluated in that order and the first
8
+ # non-error result will be used. If all sources return an error
9
+ # then the default value is used.
10
+ class MultipleSourceProvider
11
+ extend T::Sig
12
+
13
+ include Provider
14
+
15
+ sig { params(providers: T::Array[Provider]).void }
16
+ def initialize(providers:)
17
+ @providers = providers
18
+ end
19
+
20
+ sig { override.returns(ProviderMetadata) }
21
+ def metadata
22
+ ProviderMetadata.new(name: "Multiple Sources: #{providers.map(&:metadata).map(&:name).join(", ")}")
23
+ end
24
+
25
+ sig { override.returns(T::Array[Hook]) }
26
+ def hooks
27
+ providers.flat_map(&:hooks)
28
+ end
29
+
30
+ sig do
31
+ override
32
+ .params(
33
+ flag_key: String,
34
+ default_value: T::Boolean,
35
+ context: T.nilable(EvaluationContext)
36
+ )
37
+ .returns(ResolutionDetails[T::Boolean])
38
+ end
39
+ def resolve_boolean_value(flag_key:, default_value:, context: nil)
40
+ resolve_from_sources(default_value: default_value) do |provider|
41
+ provider.resolve_boolean_value(flag_key: flag_key, default_value: default_value)
42
+ end
43
+ end
44
+
45
+ sig do
46
+ override
47
+ .params(
48
+ flag_key: String,
49
+ default_value: Numeric,
50
+ context: T.nilable(EvaluationContext)
51
+ )
52
+ .returns(ResolutionDetails[Numeric])
53
+ end
54
+ def resolve_number_value(flag_key:, default_value:, context: nil)
55
+ resolve_from_sources(default_value: default_value) do |provider|
56
+ provider.resolve_number_value(flag_key: flag_key, default_value: default_value)
57
+ end
58
+ end
59
+
60
+ sig do
61
+ override
62
+ .params(
63
+ flag_key: String,
64
+ default_value: Structure,
65
+ context: T.nilable(EvaluationContext)
66
+ )
67
+ .returns(ResolutionDetails[Structure])
68
+ end
69
+ def resolve_structure_value(flag_key:, default_value:, context: nil)
70
+ resolve_from_sources(default_value: default_value) do |provider|
71
+ provider.resolve_structure_value(flag_key: flag_key, default_value: default_value)
72
+ end
73
+ end
74
+
75
+ sig do
76
+ override
77
+ .params(
78
+ flag_key: String,
79
+ default_value: String,
80
+ context: T.nilable(EvaluationContext)
81
+ )
82
+ .returns(ResolutionDetails[String])
83
+ end
84
+ def resolve_string_value(flag_key:, default_value:, context: nil)
85
+ resolve_from_sources(default_value: default_value) do |provider|
86
+ provider.resolve_string_value(flag_key: flag_key, default_value: default_value)
87
+ end
88
+ end
89
+
90
+ private
91
+
92
+ sig { returns(T::Array[Provider]) }
93
+ attr_reader :providers
94
+
95
+ # rubocop:disable Metrics/MethodLength
96
+ sig do
97
+ type_parameters(:U)
98
+ .params(
99
+ default_value: T.type_parameter(:U),
100
+ blk: T.proc.params(arg0: Provider).returns(ResolutionDetails[T.type_parameter(:U)])
101
+ )
102
+ .returns(ResolutionDetails[T.type_parameter(:U)])
103
+ end
104
+ def resolve_from_sources(default_value:, &blk)
105
+ successful_details = providers.each do |provider|
106
+ details = yield(provider)
107
+
108
+ break details if details.error_code.nil?
109
+ rescue StandardError
110
+ next
111
+ end
112
+
113
+ if successful_details.is_a?(ResolutionDetails)
114
+ successful_details
115
+ else
116
+ ResolutionDetails.new(value: default_value, error_code: ErrorCode::General, reason: "ERROR")
117
+ end
118
+ end
119
+ # rubocop:enable Metrics/MethodLength
120
+ end
121
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openfeature-sdk-sorbet
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Max VelDink
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-05-15 00:00:00.000000000 Z
11
+ date: 2023-05-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sorbet-runtime
@@ -52,7 +52,7 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '2.6'
55
- description:
55
+ description:
56
56
  email:
57
57
  - maxveldink@gmail.com
58
58
  executables: []
@@ -80,6 +80,7 @@ files:
80
80
  - lib/open_feature/evaluation_options.rb
81
81
  - lib/open_feature/flag_metadata.rb
82
82
  - lib/open_feature/hook.rb
83
+ - lib/open_feature/multiple_source_provider.rb
83
84
  - lib/open_feature/no_op_provider.rb
84
85
  - lib/open_feature/provider.rb
85
86
  - lib/open_feature/provider_metadata.rb
@@ -129,7 +130,7 @@ metadata:
129
130
  homepage_uri: https://github.com/maxveldink/openfeature-sdk-sorbet
130
131
  source_code_uri: https://github.com/maxveldink/openfeature-sdk-sorbet
131
132
  changelog_uri: https://github.com/maxveldink/openfeature-sdk-sorbet/blob/main/CHANGELOG.md
132
- post_install_message:
133
+ post_install_message:
133
134
  rdoc_options: []
134
135
  require_paths:
135
136
  - lib
@@ -144,8 +145,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
144
145
  - !ruby/object:Gem::Version
145
146
  version: '0'
146
147
  requirements: []
147
- rubygems_version: 3.4.12
148
- signing_key:
148
+ rubygems_version: 3.4.10
149
+ signing_key:
149
150
  specification_version: 4
150
151
  summary: Sorbet-aware implemention of the OpenFeature specification
151
152
  test_files: []