openfeature-sdk 0.6.2 → 0.6.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.release-please-manifest.json +1 -1
- data/CHANGELOG.md +13 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +39 -1
- data/README.md +2 -2
- data/Rakefile +5 -0
- data/cucumber.yml +2 -0
- data/lib/open_feature/sdk/api.rb +6 -1
- data/lib/open_feature/sdk/client.rb +46 -15
- data/lib/open_feature/sdk/client_metadata.rb +3 -1
- data/lib/open_feature/sdk/configuration.rb +47 -18
- data/lib/open_feature/sdk/hooks/hook_executor.rb +23 -1
- data/lib/open_feature/sdk/provider/in_memory_provider.rb +3 -1
- data/lib/open_feature/sdk/version.rb +1 -1
- data/renovate.json +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bd3ec1b654a844eaa7bcafe400d6d2075199fa49ba6823aad1c8e1ce8c05a526
|
|
4
|
+
data.tar.gz: 3d159cb4f4df832154cfa7a4657ee53f357827a3d55dcbe124bf4716248e24b8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 66667a224162e00b882ad73b45e5d2825cc35f47007ca961749cc7115cbe1223d881be0cfff89eb4a5d3fd3f0235c2548f7a89420de9ff7bb3a6b0fd4bcada65
|
|
7
|
+
data.tar.gz: f799ac085e5593bc9b14a040ebddc8326c57ff46e36285ed0ea9b44008dd0d8d58a149a1c0f7fc9be50aeb3cf8d60ffc2859f2b3f9099d49e1db3df6f795b669
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.6.3](https://github.com/open-feature/ruby-sdk/compare/v0.6.2...v0.6.3) (2026-03-07)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* close spec compliance gaps for OpenFeature v0.8.0 ([#237](https://github.com/open-feature/ruby-sdk/issues/237)) ([9a87d04](https://github.com/open-feature/ruby-sdk/commit/9a87d04d5f261ea06e073f405c15613db7099d8a))
|
|
9
|
+
* enable Gherkin feature tests ([#50](https://github.com/open-feature/ruby-sdk/issues/50)) ([#233](https://github.com/open-feature/ruby-sdk/issues/233)) ([95845ba](https://github.com/open-feature/ruby-sdk/commit/95845ba6ec26357d9c0895d310361e411f85da11))
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
### Bug Fixes
|
|
13
|
+
|
|
14
|
+
* close remaining MUST-level spec compliance gaps ([#238](https://github.com/open-feature/ruby-sdk/issues/238)) ([1d08491](https://github.com/open-feature/ruby-sdk/commit/1d084911964c8672dd66b23834eec6f14e453749))
|
|
15
|
+
|
|
3
16
|
## [0.6.2](https://github.com/open-feature/ruby-sdk/compare/v0.6.1...v0.6.2) (2026-03-07)
|
|
4
17
|
|
|
5
18
|
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,12 +1,40 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
openfeature-sdk (0.6.
|
|
4
|
+
openfeature-sdk (0.6.3)
|
|
5
5
|
|
|
6
6
|
GEM
|
|
7
7
|
remote: https://rubygems.org/
|
|
8
8
|
specs:
|
|
9
9
|
ast (2.4.3)
|
|
10
|
+
base64 (0.3.0)
|
|
11
|
+
bigdecimal (4.0.1)
|
|
12
|
+
builder (3.3.0)
|
|
13
|
+
cucumber (10.2.0)
|
|
14
|
+
base64 (~> 0.2)
|
|
15
|
+
builder (~> 3.2)
|
|
16
|
+
cucumber-ci-environment (> 9, < 12)
|
|
17
|
+
cucumber-core (> 15, < 17)
|
|
18
|
+
cucumber-cucumber-expressions (> 17, < 20)
|
|
19
|
+
cucumber-html-formatter (> 21, < 23)
|
|
20
|
+
diff-lcs (~> 1.5)
|
|
21
|
+
logger (~> 1.6)
|
|
22
|
+
mini_mime (~> 1.1)
|
|
23
|
+
multi_test (~> 1.1)
|
|
24
|
+
sys-uname (~> 1.3)
|
|
25
|
+
cucumber-ci-environment (11.0.0)
|
|
26
|
+
cucumber-core (16.2.0)
|
|
27
|
+
cucumber-gherkin (> 36, < 40)
|
|
28
|
+
cucumber-messages (> 31, < 33)
|
|
29
|
+
cucumber-tag-expressions (> 6, < 9)
|
|
30
|
+
cucumber-cucumber-expressions (19.0.0)
|
|
31
|
+
bigdecimal
|
|
32
|
+
cucumber-gherkin (39.0.0)
|
|
33
|
+
cucumber-messages (>= 31, < 33)
|
|
34
|
+
cucumber-html-formatter (22.3.0)
|
|
35
|
+
cucumber-messages (> 23, < 33)
|
|
36
|
+
cucumber-messages (32.2.0)
|
|
37
|
+
cucumber-tag-expressions (8.1.0)
|
|
10
38
|
date (3.5.1)
|
|
11
39
|
debug (1.11.1)
|
|
12
40
|
irb (~> 1.10)
|
|
@@ -14,6 +42,7 @@ GEM
|
|
|
14
42
|
diff-lcs (1.6.2)
|
|
15
43
|
docile (1.4.1)
|
|
16
44
|
erb (6.0.2)
|
|
45
|
+
ffi (1.17.3)
|
|
17
46
|
io-console (0.8.2)
|
|
18
47
|
irb (1.17.0)
|
|
19
48
|
pp (>= 0.6.0)
|
|
@@ -23,7 +52,11 @@ GEM
|
|
|
23
52
|
json (2.18.1)
|
|
24
53
|
language_server-protocol (3.17.0.5)
|
|
25
54
|
lint_roller (1.1.0)
|
|
55
|
+
logger (1.7.0)
|
|
26
56
|
markly (0.15.2)
|
|
57
|
+
memoist3 (1.0.0)
|
|
58
|
+
mini_mime (1.1.5)
|
|
59
|
+
multi_test (1.1.0)
|
|
27
60
|
parallel (1.27.0)
|
|
28
61
|
parser (3.3.10.2)
|
|
29
62
|
ast (~> 2.4.1)
|
|
@@ -100,6 +133,9 @@ GEM
|
|
|
100
133
|
lint_roller (~> 1.1)
|
|
101
134
|
rubocop-performance (~> 1.26.0)
|
|
102
135
|
stringio (3.2.0)
|
|
136
|
+
sys-uname (1.5.0)
|
|
137
|
+
ffi (~> 1.1)
|
|
138
|
+
memoist3 (~> 1.0.0)
|
|
103
139
|
timecop (0.9.10)
|
|
104
140
|
tsort (0.2.0)
|
|
105
141
|
unicode-display_width (3.2.0)
|
|
@@ -120,7 +156,9 @@ PLATFORMS
|
|
|
120
156
|
x86_64-linux
|
|
121
157
|
|
|
122
158
|
DEPENDENCIES
|
|
159
|
+
cucumber (~> 10.0)
|
|
123
160
|
debug
|
|
161
|
+
logger
|
|
124
162
|
markly
|
|
125
163
|
openfeature-sdk!
|
|
126
164
|
rake (~> 13.0)
|
data/README.md
CHANGED
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
</a>
|
|
18
18
|
<!-- x-release-please-start-version -->
|
|
19
19
|
|
|
20
|
-
<a href="https://github.com/open-feature/ruby-sdk/releases/tag/v0.6.
|
|
21
|
-
<img alt="Release" src="https://img.shields.io/static/v1?label=release&message=v0.6.
|
|
20
|
+
<a href="https://github.com/open-feature/ruby-sdk/releases/tag/v0.6.3">
|
|
21
|
+
<img alt="Release" src="https://img.shields.io/static/v1?label=release&message=v0.6.3&color=blue&style=for-the-badge" />
|
|
22
22
|
</a>
|
|
23
23
|
|
|
24
24
|
<!-- x-release-please-end -->
|
data/Rakefile
CHANGED
data/cucumber.yml
ADDED
data/lib/open_feature/sdk/api.rb
CHANGED
|
@@ -34,7 +34,7 @@ module OpenFeature
|
|
|
34
34
|
include Singleton # Satisfies Flag Evaluation API Requirement 1.1.1
|
|
35
35
|
extend Forwardable
|
|
36
36
|
|
|
37
|
-
def_delegators :configuration, :provider, :set_provider, :set_provider_and_wait, :hooks, :evaluation_context
|
|
37
|
+
def_delegators :configuration, :provider, :set_provider, :set_provider_and_wait, :hooks, :add_hooks, :evaluation_context
|
|
38
38
|
|
|
39
39
|
def configuration
|
|
40
40
|
@configuration ||= Configuration.new
|
|
@@ -54,6 +54,11 @@ module OpenFeature
|
|
|
54
54
|
Client.new(provider: Provider::NoOpProvider.new, evaluation_context:)
|
|
55
55
|
end
|
|
56
56
|
|
|
57
|
+
def provider_metadata(domain: nil)
|
|
58
|
+
prov = provider(domain: domain)
|
|
59
|
+
prov.metadata if prov&.respond_to?(:metadata)
|
|
60
|
+
end
|
|
61
|
+
|
|
57
62
|
def add_handler(event_type, handler)
|
|
58
63
|
configuration.add_handler(event_type, handler)
|
|
59
64
|
end
|
|
@@ -28,6 +28,10 @@ module OpenFeature
|
|
|
28
28
|
@hooks = []
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
+
def add_hooks(*new_hooks)
|
|
32
|
+
@hooks.concat(new_hooks.flatten)
|
|
33
|
+
end
|
|
34
|
+
|
|
31
35
|
def provider_status
|
|
32
36
|
OpenFeature::SDK.configuration.provider_state(@provider)
|
|
33
37
|
end
|
|
@@ -70,27 +74,40 @@ module OpenFeature
|
|
|
70
74
|
def fetch_details(type:, flag_key:, default_value:, evaluation_context: nil, invocation_hooks: [], hook_hints: nil)
|
|
71
75
|
validate_default_value_type(type, default_value)
|
|
72
76
|
|
|
73
|
-
if OpenFeature::SDK.configuration.provider_tracked?(@provider)
|
|
74
|
-
error_code = short_circuit_error_code(provider_status)
|
|
75
|
-
if error_code
|
|
76
|
-
resolution = Provider::ResolutionDetails.new(
|
|
77
|
-
value: default_value,
|
|
78
|
-
error_code: error_code,
|
|
79
|
-
reason: Provider::Reason::ERROR
|
|
80
|
-
)
|
|
81
|
-
return EvaluationDetails.new(flag_key: flag_key, resolution_details: resolution)
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
|
|
85
77
|
built_context = build_evaluation_context(evaluation_context)
|
|
86
78
|
|
|
87
79
|
# Assemble ordered hooks: API → Client → Invocation → Provider (spec 4.4.2)
|
|
88
80
|
provider_hooks = @provider.respond_to?(:hooks) ? Array(@provider.hooks) : []
|
|
89
81
|
ordered_hooks = [*OpenFeature::SDK.hooks, *@hooks, *invocation_hooks, *provider_hooks]
|
|
90
82
|
|
|
83
|
+
# Check for short-circuit conditions (spec 1.7.6 + 1.7.7)
|
|
84
|
+
short_circuit_code = nil
|
|
85
|
+
if OpenFeature::SDK.configuration.provider_tracked?(@provider)
|
|
86
|
+
short_circuit_code = short_circuit_error_code(provider_status)
|
|
87
|
+
end
|
|
88
|
+
|
|
91
89
|
# Fast path: skip hook ceremony when no hooks are registered
|
|
92
90
|
if ordered_hooks.empty?
|
|
93
|
-
|
|
91
|
+
if short_circuit_code
|
|
92
|
+
resolution = Provider::ResolutionDetails.new(
|
|
93
|
+
value: default_value,
|
|
94
|
+
error_code: short_circuit_code,
|
|
95
|
+
reason: Provider::Reason::ERROR
|
|
96
|
+
)
|
|
97
|
+
return EvaluationDetails.new(flag_key: flag_key, resolution_details: resolution)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
begin
|
|
101
|
+
return evaluate_flag(type: type, flag_key: flag_key, default_value: default_value, evaluation_context: built_context)
|
|
102
|
+
rescue => e
|
|
103
|
+
resolution = Provider::ResolutionDetails.new(
|
|
104
|
+
value: default_value,
|
|
105
|
+
error_code: Provider::ErrorCode::GENERAL,
|
|
106
|
+
reason: Provider::Reason::ERROR,
|
|
107
|
+
error_message: e.message
|
|
108
|
+
)
|
|
109
|
+
return EvaluationDetails.new(flag_key: flag_key, resolution_details: resolution)
|
|
110
|
+
end
|
|
94
111
|
end
|
|
95
112
|
|
|
96
113
|
hook_context = Hooks::HookContext.new(
|
|
@@ -111,8 +128,21 @@ module OpenFeature
|
|
|
111
128
|
end
|
|
112
129
|
|
|
113
130
|
executor = Hooks::HookExecutor.new(logger: OpenFeature::SDK.configuration.logger)
|
|
114
|
-
|
|
115
|
-
|
|
131
|
+
|
|
132
|
+
if short_circuit_code
|
|
133
|
+
# Spec 1.7.6 + 1.7.7: short-circuit must still run error hooks and finally hooks
|
|
134
|
+
resolution = Provider::ResolutionDetails.new(
|
|
135
|
+
value: default_value,
|
|
136
|
+
error_code: short_circuit_code,
|
|
137
|
+
reason: Provider::Reason::ERROR
|
|
138
|
+
)
|
|
139
|
+
evaluation_details = EvaluationDetails.new(flag_key: flag_key, resolution_details: resolution)
|
|
140
|
+
executor.run_short_circuit(ordered_hooks: ordered_hooks, hook_context: hook_context, hints: hints, evaluation_details: evaluation_details)
|
|
141
|
+
evaluation_details
|
|
142
|
+
else
|
|
143
|
+
executor.execute(ordered_hooks: ordered_hooks, hook_context: hook_context, hints: hints) do |hctx|
|
|
144
|
+
evaluate_flag(type: type, flag_key: flag_key, default_value: default_value, evaluation_context: hctx.evaluation_context)
|
|
145
|
+
end
|
|
116
146
|
end
|
|
117
147
|
end
|
|
118
148
|
|
|
@@ -128,6 +158,7 @@ module OpenFeature
|
|
|
128
158
|
resolution_details.value = default_value
|
|
129
159
|
resolution_details.error_code = Provider::ErrorCode::TYPE_MISMATCH
|
|
130
160
|
resolution_details.reason = Provider::Reason::ERROR
|
|
161
|
+
resolution_details.variant = nil
|
|
131
162
|
end
|
|
132
163
|
|
|
133
164
|
EvaluationDetails.new(flag_key: flag_key, resolution_details: resolution_details)
|
|
@@ -31,6 +31,10 @@ module OpenFeature
|
|
|
31
31
|
@client_handlers_mutex = Mutex.new
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
+
def add_hooks(*new_hooks)
|
|
35
|
+
@hooks.concat(new_hooks.flatten)
|
|
36
|
+
end
|
|
37
|
+
|
|
34
38
|
def provider(domain: nil)
|
|
35
39
|
@providers[domain] || @providers[nil]
|
|
36
40
|
end
|
|
@@ -85,9 +89,11 @@ module OpenFeature
|
|
|
85
89
|
end
|
|
86
90
|
|
|
87
91
|
def shutdown
|
|
88
|
-
providers_to_shutdown = @provider_mutex.synchronize { @providers.values.uniq }
|
|
92
|
+
providers_to_shutdown = @provider_mutex.synchronize { @providers.values.uniq(&:object_id) }
|
|
89
93
|
|
|
90
94
|
providers_to_shutdown.each do |prov|
|
|
95
|
+
# Spec 1.7.9: Set provider state to NOT_READY before shutdown
|
|
96
|
+
@provider_state_registry.set_initial_state(prov, ProviderState::NOT_READY)
|
|
91
97
|
prov.shutdown if prov.respond_to?(:shutdown)
|
|
92
98
|
rescue => e
|
|
93
99
|
@logger&.warn("Error shutting down provider #{prov&.class&.name || "unknown"}: #{e.message}")
|
|
@@ -107,34 +113,46 @@ module OpenFeature
|
|
|
107
113
|
@provider_mutex.synchronize do
|
|
108
114
|
@providers.clear
|
|
109
115
|
end
|
|
116
|
+
@hooks.clear
|
|
117
|
+
@evaluation_context = nil
|
|
118
|
+
@transaction_context_propagator = nil
|
|
110
119
|
end
|
|
111
120
|
|
|
112
121
|
def set_provider_internal(provider, domain:, wait_for_init:)
|
|
113
122
|
# Capture evaluation context before acquiring mutex to prevent race conditions
|
|
114
123
|
context_for_init = @evaluation_context
|
|
115
124
|
|
|
116
|
-
old_provider
|
|
125
|
+
old_provider = nil
|
|
126
|
+
needs_init = false
|
|
127
|
+
needs_shutdown = false
|
|
117
128
|
|
|
118
129
|
@provider_mutex.synchronize do
|
|
119
130
|
old_provider = @providers[domain]
|
|
120
131
|
|
|
121
|
-
# Remove old provider state to prevent memory leaks
|
|
122
|
-
@provider_state_registry.remove_provider(old_provider)
|
|
123
|
-
|
|
124
132
|
new_providers = @providers.dup
|
|
125
133
|
new_providers[domain] = provider
|
|
126
134
|
@providers = new_providers
|
|
127
135
|
|
|
128
|
-
|
|
136
|
+
# Spec 1.1.2.2: Only initialize if the provider is not already active
|
|
137
|
+
# (i.e., not already bound to another domain)
|
|
138
|
+
already_active = @providers.any? { |d, p| d != domain && p.equal?(provider) && @provider_state_registry.tracked?(p) }
|
|
139
|
+
needs_init = !already_active
|
|
129
140
|
|
|
130
|
-
|
|
141
|
+
if needs_init
|
|
142
|
+
@provider_state_registry.set_initial_state(provider)
|
|
143
|
+
provider.send(:attach, self) if provider.is_a?(Provider::EventEmitter)
|
|
144
|
+
end
|
|
131
145
|
|
|
132
|
-
|
|
146
|
+
# Spec 1.1.2.3: Only shutdown old provider if it's no longer bound to any domain
|
|
147
|
+
if old_provider && !old_provider.equal?(provider)
|
|
148
|
+
still_bound = @providers.any? { |_, p| p.equal?(old_provider) }
|
|
149
|
+
needs_shutdown = !still_bound
|
|
150
|
+
@provider_state_registry.remove_provider(old_provider) unless still_bound
|
|
151
|
+
end
|
|
133
152
|
end
|
|
134
153
|
|
|
135
154
|
# Shutdown old provider outside mutex to avoid blocking other operations
|
|
136
|
-
|
|
137
|
-
if old_provider && old_provider != provider
|
|
155
|
+
if needs_shutdown
|
|
138
156
|
begin
|
|
139
157
|
old_provider.shutdown if old_provider.respond_to?(:shutdown)
|
|
140
158
|
rescue => e
|
|
@@ -143,12 +161,17 @@ module OpenFeature
|
|
|
143
161
|
end
|
|
144
162
|
|
|
145
163
|
# Initialize provider outside the mutex to avoid blocking other operations
|
|
146
|
-
if
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
164
|
+
if needs_init
|
|
165
|
+
if wait_for_init
|
|
166
|
+
init_provider(provider, context_for_init, raise_on_error: true)
|
|
167
|
+
else
|
|
168
|
+
Thread.new do
|
|
169
|
+
init_provider(provider, context_for_init, raise_on_error: false)
|
|
170
|
+
end
|
|
151
171
|
end
|
|
172
|
+
elsif wait_for_init
|
|
173
|
+
# Provider already active; no init needed but still dispatch READY
|
|
174
|
+
dispatch_provider_event(provider, ProviderEvent::PROVIDER_READY)
|
|
152
175
|
end
|
|
153
176
|
end
|
|
154
177
|
|
|
@@ -164,16 +187,22 @@ module OpenFeature
|
|
|
164
187
|
|
|
165
188
|
dispatch_provider_event(provider, ProviderEvent::PROVIDER_READY)
|
|
166
189
|
rescue => e
|
|
190
|
+
# Spec 1.7.8: Propagate error code from provider if available
|
|
191
|
+
error_code = if e.respond_to?(:error_code) && e.error_code
|
|
192
|
+
e.error_code
|
|
193
|
+
else
|
|
194
|
+
Provider::ErrorCode::GENERAL
|
|
195
|
+
end
|
|
196
|
+
|
|
167
197
|
dispatch_provider_event(provider, ProviderEvent::PROVIDER_ERROR,
|
|
168
|
-
error_code:
|
|
198
|
+
error_code: error_code,
|
|
169
199
|
message: e.message)
|
|
170
200
|
|
|
171
201
|
if raise_on_error
|
|
172
|
-
# Re-raise as ProviderInitializationError for synchronous callers
|
|
173
202
|
raise ProviderInitializationError.new(
|
|
174
203
|
"Provider #{provider.class.name} initialization failed: #{e.message}",
|
|
175
204
|
provider:,
|
|
176
|
-
error_code:
|
|
205
|
+
error_code: error_code,
|
|
177
206
|
original_error: e
|
|
178
207
|
)
|
|
179
208
|
end
|
|
@@ -18,6 +18,20 @@ module OpenFeature
|
|
|
18
18
|
@logger = logger
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
+
# Runs error hooks and finally hooks for a short-circuit evaluation
|
|
22
|
+
# (spec 1.7.6 + 1.7.7). Before hooks and after hooks are NOT run.
|
|
23
|
+
#
|
|
24
|
+
# @param ordered_hooks [Array] hooks in before-order
|
|
25
|
+
# @param hook_context [HookContext] the hook context
|
|
26
|
+
# @param hints [Hints] hook hints
|
|
27
|
+
# @param evaluation_details [EvaluationDetails] the short-circuit result
|
|
28
|
+
def run_short_circuit(ordered_hooks:, hook_context:, hints:, evaluation_details:)
|
|
29
|
+
error = StandardError.new(evaluation_details.error_code)
|
|
30
|
+
run_error_hooks(ordered_hooks, hook_context, error, hints)
|
|
31
|
+
ensure
|
|
32
|
+
run_finally_hooks(ordered_hooks, hook_context, evaluation_details, hints)
|
|
33
|
+
end
|
|
34
|
+
|
|
21
35
|
# Executes the full hook lifecycle around the flag evaluation block.
|
|
22
36
|
#
|
|
23
37
|
# @param ordered_hooks [Array] hooks in before-order (API, Client, Invocation, Provider)
|
|
@@ -31,7 +45,15 @@ module OpenFeature
|
|
|
31
45
|
begin
|
|
32
46
|
run_before_hooks(ordered_hooks, hook_context, hints)
|
|
33
47
|
evaluation_details = evaluate_block.call(hook_context)
|
|
34
|
-
|
|
48
|
+
|
|
49
|
+
# Spec 4.3.6: If evaluation resulted in an error (e.g. FLAG_NOT_FOUND,
|
|
50
|
+
# TYPE_MISMATCH), run error hooks instead of after hooks.
|
|
51
|
+
if evaluation_details.error_code
|
|
52
|
+
error = StandardError.new(evaluation_details.error_message || evaluation_details.error_code)
|
|
53
|
+
run_error_hooks(ordered_hooks, hook_context, error, hints)
|
|
54
|
+
else
|
|
55
|
+
run_after_hooks(ordered_hooks, hook_context, evaluation_details, hints)
|
|
56
|
+
end
|
|
35
57
|
rescue => e
|
|
36
58
|
run_error_hooks(ordered_hooks, hook_context, e, hints)
|
|
37
59
|
|
|
@@ -29,8 +29,10 @@ module OpenFeature
|
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
def update_flags(new_flags)
|
|
32
|
+
old_keys = @flags.keys
|
|
32
33
|
@flags = new_flags.dup
|
|
33
|
-
|
|
34
|
+
changed_keys = (old_keys | new_flags.keys)
|
|
35
|
+
emit_provider_changed(changed_keys)
|
|
34
36
|
end
|
|
35
37
|
|
|
36
38
|
def fetch_boolean_value(flag_key:, default_value:, evaluation_context: nil)
|
data/renovate.json
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: openfeature-sdk
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.6.
|
|
4
|
+
version: 0.6.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- OpenFeature Authors
|
|
@@ -159,6 +159,7 @@ files:
|
|
|
159
159
|
- LICENSE
|
|
160
160
|
- README.md
|
|
161
161
|
- Rakefile
|
|
162
|
+
- cucumber.yml
|
|
162
163
|
- lib/open_feature/sdk.rb
|
|
163
164
|
- lib/open_feature/sdk/api.rb
|
|
164
165
|
- lib/open_feature/sdk/client.rb
|