devcycle-ruby-server-sdk 3.7.0 → 3.8.0
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/Gemfile +1 -0
- data/LICENSE +1 -1
- data/devcycle-ruby-server-sdk.gemspec +2 -2
- data/lib/devcycle-ruby-server-sdk/api/client.rb +15 -2
- data/lib/devcycle-ruby-server-sdk/api/dev_cycle_provider.rb +10 -1
- data/lib/devcycle-ruby-server-sdk/eval_reasons.rb +3 -0
- data/lib/devcycle-ruby-server-sdk/localbucketing/local_bucketing.rb +8 -8
- data/lib/devcycle-ruby-server-sdk/models/variable.rb +2 -1
- data/lib/devcycle-ruby-server-sdk/version.rb +1 -1
- data/spec/api/devcycle_api_spec.rb +83 -0
- data/spec/spec_helper.rb +4 -0
- metadata +5 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5b3044307e6ee4e30c1a53aeac3d62eceaaac8ea86fc380b1a41bbf15294ce98
|
|
4
|
+
data.tar.gz: 3fdb48a7217e4390bfe4f53f2e438324803cd9bc8b32a2f91c31a7e7783a32bf
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: af96f97ff9a13800b415f59777446ea075535e24959939e737b845599201c6b1d8ddce1d170b099837ee2d2b91dee7039b8354298f009df0e2e0eeb0d731c071
|
|
7
|
+
data.tar.gz: 021bfd22df2c904f03e4e089387a8914b078e9b70d237f12551cfd036665120cba7df2ba3f09b1df62177b6fd9e1b576f7e75c23415880da4c54c8705445eee8
|
data/Gemfile
CHANGED
data/LICENSE
CHANGED
|
@@ -24,13 +24,13 @@ Gem::Specification.new do |s|
|
|
|
24
24
|
s.required_ruby_version = ">= 3.2"
|
|
25
25
|
|
|
26
26
|
s.add_runtime_dependency 'typhoeus', '~> 1.0', '>= 1.0.1'
|
|
27
|
-
s.add_runtime_dependency 'wasmtime', '
|
|
27
|
+
s.add_runtime_dependency 'wasmtime', '39.0.1'
|
|
28
28
|
s.add_runtime_dependency 'concurrent-ruby', '~> 1.2.0'
|
|
29
29
|
s.add_runtime_dependency 'sorbet-runtime', '>= 0.5.11481'
|
|
30
30
|
s.add_runtime_dependency 'oj', '~> 3.0'
|
|
31
31
|
s.add_runtime_dependency 'google-protobuf', '~> 3.22'
|
|
32
32
|
s.add_runtime_dependency 'ld-eventsource', '~> 2.2.3'
|
|
33
|
-
s.add_runtime_dependency 'openfeature-sdk', '~> 0.4.
|
|
33
|
+
s.add_runtime_dependency 'openfeature-sdk', '~> 0.4.1'
|
|
34
34
|
|
|
35
35
|
s.add_development_dependency 'rspec', '~> 3.6', '>= 3.6.0'
|
|
36
36
|
|
|
@@ -325,14 +325,27 @@ module DevCycle
|
|
|
325
325
|
if @api_client.config.debugging
|
|
326
326
|
@api_client.config.logger.debug "API called: DevCycle::Client#variable\nData: #{data.inspect}\nStatus code: #{status_code}\nHeaders: #{headers}"
|
|
327
327
|
end
|
|
328
|
+
if default && data.type
|
|
329
|
+
api_type_to_ruby_class = {
|
|
330
|
+
'Boolean' => [TrueClass, FalseClass],
|
|
331
|
+
'Number' => [Integer, Float],
|
|
332
|
+
'String' => [String],
|
|
333
|
+
'JSON' => [Hash]
|
|
334
|
+
}
|
|
335
|
+
ruby_classes = api_type_to_ruby_class[data.type.to_s]
|
|
336
|
+
unless ruby_classes && ruby_classes.any? { |klass| default.is_a?(klass) }
|
|
337
|
+
eval = { reason: DevCycle::EVAL_REASONS::DEFAULT, details: DevCycle::DEFAULT_REASON_DETAILS::TYPE_MISMATCH }
|
|
338
|
+
return Variable.new(key: key, value: default, isDefaulted: true, eval: eval)
|
|
339
|
+
end
|
|
340
|
+
end
|
|
328
341
|
return data
|
|
329
342
|
rescue ApiError => error
|
|
330
343
|
if error.code != 404
|
|
331
344
|
@api_client.config.logger.error("Failed to retrieve variable value: #{error.message}")
|
|
332
345
|
end
|
|
333
346
|
|
|
334
|
-
return Variable.new(key: key, value: default, isDefaulted: true)
|
|
335
|
-
end
|
|
347
|
+
return Variable.new(key: key, value: default, isDefaulted: true, eval: { reason: DevCycle::EVAL_REASONS::DEFAULT, details: DevCycle::DEFAULT_REASON_DETAILS::ERROR })
|
|
348
|
+
end
|
|
336
349
|
end
|
|
337
350
|
|
|
338
351
|
# Get all variables by key for user data
|
|
@@ -32,7 +32,16 @@ module DevCycle
|
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
def fetch_integer_value(flag_key:, default_value:, evaluation_context: nil)
|
|
35
|
-
@client.variable(Provider.user_from_openfeature_context(evaluation_context), flag_key, default_value)
|
|
35
|
+
variable = @client.variable(Provider.user_from_openfeature_context(evaluation_context), flag_key, default_value)
|
|
36
|
+
|
|
37
|
+
Variable.new(
|
|
38
|
+
key: variable.key,
|
|
39
|
+
type: variable.type,
|
|
40
|
+
value: variable.value.to_i,
|
|
41
|
+
defaultValue: variable.defaultValue,
|
|
42
|
+
isDefaulted: variable.isDefaulted,
|
|
43
|
+
eval: variable.eval
|
|
44
|
+
)
|
|
36
45
|
end
|
|
37
46
|
|
|
38
47
|
def fetch_float_value(flag_key:, default_value:, evaluation_context: nil)
|
|
@@ -27,14 +27,14 @@ module DevCycle
|
|
|
27
27
|
# added to ensure that there is no processes deadlock when compiling wasm before forking
|
|
28
28
|
|
|
29
29
|
@@wasmmodule = Wasmtime::Module.from_file(@@engine, "#{__dir__}/bucketing-lib.release.wasm")
|
|
30
|
-
@@
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
@@
|
|
37
|
-
|
|
30
|
+
@@wasi_config = Wasmtime::WasiConfig.new
|
|
31
|
+
.inherit_stdout
|
|
32
|
+
.inherit_stderr
|
|
33
|
+
.set_argv(ARGV)
|
|
34
|
+
.set_env(ENV)
|
|
35
|
+
@@store = Wasmtime::Store.new(@@engine, wasi_p1_config: @@wasi_config)
|
|
36
|
+
@@linker = Wasmtime::Linker.new(@@engine)
|
|
37
|
+
Wasmtime::WASI::P1.add_to_linker_sync(@@linker)
|
|
38
38
|
|
|
39
39
|
@@linker.func_new("env", "Date.now", [], [:f64]) do |_caller|
|
|
40
40
|
DateTime.now.strftime("%Q").to_i
|
|
@@ -12,6 +12,9 @@ OpenAPI Generator version: 5.3.0
|
|
|
12
12
|
|
|
13
13
|
require 'spec_helper'
|
|
14
14
|
require 'json'
|
|
15
|
+
require 'webmock'
|
|
16
|
+
|
|
17
|
+
include WebMock::API
|
|
15
18
|
|
|
16
19
|
# Unit tests for DevCycle::Client
|
|
17
20
|
# Automatically generated by openapi-generator (https://openapi-generator.tech)
|
|
@@ -68,6 +71,8 @@ describe 'DevCycle::Client' do
|
|
|
68
71
|
it 'should work' do
|
|
69
72
|
result = @api_instance.variable(@user, "ruby-example-tests-default", false)
|
|
70
73
|
expect(result.isDefaulted).to eq true
|
|
74
|
+
expect(result.eval[:reason]).to eq "DEFAULT"
|
|
75
|
+
expect(result.eval[:details]).to eq "Error"
|
|
71
76
|
|
|
72
77
|
result = @api_instance.variable_value(@user, "ruby-example-tests-default", true)
|
|
73
78
|
expect(result).to eq true
|
|
@@ -88,6 +93,51 @@ describe 'DevCycle::Client' do
|
|
|
88
93
|
|
|
89
94
|
result = @api_instance.variable_value(@user, "test", true)
|
|
90
95
|
expect(result).to eq true
|
|
96
|
+
|
|
97
|
+
result = @api_instance.variable(@user, "test-number-variable", 0)
|
|
98
|
+
expect(result.isDefaulted).to eq false
|
|
99
|
+
expect(result.value).to eq 123
|
|
100
|
+
|
|
101
|
+
result = @api_instance.variable(@user, "test-number-variable", 0)
|
|
102
|
+
expect(result.isDefaulted).to eq false
|
|
103
|
+
expect(result.value).to eq 123
|
|
104
|
+
|
|
105
|
+
result = @api_instance.variable(@user, "test-float-variable", 0.0)
|
|
106
|
+
expect(result.isDefaulted).to eq false
|
|
107
|
+
expect(result.value).to eq 4.56
|
|
108
|
+
|
|
109
|
+
result = @api_instance.variable(@user, "test-string-variable", "")
|
|
110
|
+
expect(result.isDefaulted).to eq false
|
|
111
|
+
expect(result.value).to eq "on"
|
|
112
|
+
|
|
113
|
+
result = @api_instance.variable(@user, "test-json-variable", {})
|
|
114
|
+
expect(result.isDefaulted).to eq false
|
|
115
|
+
expect(result.value).to eq({:message => "a"})
|
|
116
|
+
|
|
117
|
+
result = @api_instance.variable(@user, "test", "false")
|
|
118
|
+
expect(result.isDefaulted).to eq true
|
|
119
|
+
expect(result.eval[:reason]).to eq "DEFAULT"
|
|
120
|
+
expect(result.eval[:details]).to eq "Variable Type Mismatch"
|
|
121
|
+
|
|
122
|
+
result = @api_instance.variable(@user, "test-number-variable", "123")
|
|
123
|
+
expect(result.isDefaulted).to eq true
|
|
124
|
+
expect(result.eval[:reason]).to eq "DEFAULT"
|
|
125
|
+
expect(result.eval[:details]).to eq "Variable Type Mismatch"
|
|
126
|
+
|
|
127
|
+
result = @api_instance.variable(@user, "test-number-variable", true)
|
|
128
|
+
expect(result.isDefaulted).to eq true
|
|
129
|
+
expect(result.eval[:reason]).to eq "DEFAULT"
|
|
130
|
+
expect(result.eval[:details]).to eq "Variable Type Mismatch"
|
|
131
|
+
|
|
132
|
+
result = @api_instance.variable(@user, "test-string-variable", true)
|
|
133
|
+
expect(result.isDefaulted).to eq true
|
|
134
|
+
expect(result.eval[:reason]).to eq "DEFAULT"
|
|
135
|
+
expect(result.eval[:details]).to eq "Variable Type Mismatch"
|
|
136
|
+
|
|
137
|
+
result = @api_instance.variable(@user, "test-json-variable", "on")
|
|
138
|
+
expect(result.isDefaulted).to eq true
|
|
139
|
+
expect(result.eval[:reason]).to eq "DEFAULT"
|
|
140
|
+
expect(result.eval[:details]).to eq "Variable Type Mismatch"
|
|
91
141
|
end
|
|
92
142
|
end
|
|
93
143
|
|
|
@@ -104,4 +154,37 @@ describe 'DevCycle::Client' do
|
|
|
104
154
|
end
|
|
105
155
|
end
|
|
106
156
|
|
|
157
|
+
describe 'get_variable_by_key test' do
|
|
158
|
+
before do
|
|
159
|
+
WebMock.disable_net_connect!(allow_localhost: true)
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
after do
|
|
163
|
+
WebMock.allow_net_connect!
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
it 'should work with mocked response' do
|
|
167
|
+
stub_request(:post, "https://bucketing-api.devcycle.com/v1/variables/mocked_variable").
|
|
168
|
+
to_return(status: 200, body: "{\"isDefaulted\": false, \"value\": true, \"eval\": {\"reason\": \"SPLIT\", \"details\": \"Random Distribution | All Users\", \"target_id\": \"621642332ea68943c8833c4d\"}}", headers: {})
|
|
169
|
+
|
|
170
|
+
result = @api_instance.variable(@user, "mocked_variable", false)
|
|
171
|
+
expect(result.isDefaulted).to eq false
|
|
172
|
+
expect(result.value).to eq true
|
|
173
|
+
# Use Hash syntax since eval is deserialized as a Hash
|
|
174
|
+
expect(result.eval[:reason]).to eq "SPLIT"
|
|
175
|
+
expect(result.eval[:details]).to eq "Random Distribution | All Users"
|
|
176
|
+
expect(result.eval[:target_id]).to eq "621642332ea68943c8833c4d"
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
it 'should return error details' do
|
|
180
|
+
stub_request(:post, "https://bucketing-api.devcycle.com/v1/variables/test").
|
|
181
|
+
to_return(status: 500, body: "{\"isDefaulted\": true, \"value\": false, \"eval\": {\"reason\": \"DEFAULT\", \"details\": \"Error\"}}", headers: {})
|
|
182
|
+
|
|
183
|
+
result = @api_instance.variable(@user, "test", false)
|
|
184
|
+
expect(result.isDefaulted).to eq true
|
|
185
|
+
expect(result.eval[:reason]).to eq "DEFAULT"
|
|
186
|
+
expect(result.eval[:details]).to eq "Error"
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
107
190
|
end
|
data/spec/spec_helper.rb
CHANGED
|
@@ -12,6 +12,10 @@ OpenAPI Generator version: 5.3.0
|
|
|
12
12
|
|
|
13
13
|
# load the gem
|
|
14
14
|
require 'devcycle-ruby-server-sdk'
|
|
15
|
+
require 'webmock/rspec'
|
|
16
|
+
|
|
17
|
+
# Configure WebMock to allow real HTTP requests by default, but enable it for specific tests
|
|
18
|
+
WebMock.allow_net_connect!
|
|
15
19
|
|
|
16
20
|
# The following was generated by the `rspec --init` command. Conventionally, all
|
|
17
21
|
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: devcycle-ruby-server-sdk
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.8.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- DevCycleHQ
|
|
@@ -35,14 +35,14 @@ dependencies:
|
|
|
35
35
|
requirements:
|
|
36
36
|
- - '='
|
|
37
37
|
- !ruby/object:Gem::Version
|
|
38
|
-
version:
|
|
38
|
+
version: 39.0.1
|
|
39
39
|
type: :runtime
|
|
40
40
|
prerelease: false
|
|
41
41
|
version_requirements: !ruby/object:Gem::Requirement
|
|
42
42
|
requirements:
|
|
43
43
|
- - '='
|
|
44
44
|
- !ruby/object:Gem::Version
|
|
45
|
-
version:
|
|
45
|
+
version: 39.0.1
|
|
46
46
|
- !ruby/object:Gem::Dependency
|
|
47
47
|
name: concurrent-ruby
|
|
48
48
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -119,14 +119,14 @@ dependencies:
|
|
|
119
119
|
requirements:
|
|
120
120
|
- - "~>"
|
|
121
121
|
- !ruby/object:Gem::Version
|
|
122
|
-
version: 0.4.
|
|
122
|
+
version: 0.4.1
|
|
123
123
|
type: :runtime
|
|
124
124
|
prerelease: false
|
|
125
125
|
version_requirements: !ruby/object:Gem::Requirement
|
|
126
126
|
requirements:
|
|
127
127
|
- - "~>"
|
|
128
128
|
- !ruby/object:Gem::Version
|
|
129
|
-
version: 0.4.
|
|
129
|
+
version: 0.4.1
|
|
130
130
|
- !ruby/object:Gem::Dependency
|
|
131
131
|
name: rspec
|
|
132
132
|
requirement: !ruby/object:Gem::Requirement
|