prefab-cloud-ruby 0.24.5 → 1.0.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.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +15 -0
  3. data/VERSION +1 -1
  4. data/compile_protos.sh +7 -0
  5. data/lib/prefab/client.rb +20 -46
  6. data/lib/prefab/config_client.rb +9 -12
  7. data/lib/prefab/config_resolver.rb +2 -1
  8. data/lib/prefab/config_value_unwrapper.rb +20 -9
  9. data/lib/prefab/context.rb +43 -7
  10. data/lib/prefab/context_shape_aggregator.rb +1 -1
  11. data/lib/prefab/criteria_evaluator.rb +24 -16
  12. data/lib/prefab/evaluation.rb +48 -0
  13. data/lib/prefab/evaluation_summary_aggregator.rb +85 -0
  14. data/lib/prefab/example_contexts_aggregator.rb +76 -0
  15. data/lib/prefab/exponential_backoff.rb +5 -0
  16. data/lib/prefab/feature_flag_client.rb +0 -2
  17. data/lib/prefab/log_path_aggregator.rb +1 -1
  18. data/lib/prefab/logger_client.rb +12 -13
  19. data/lib/prefab/options.rb +52 -43
  20. data/lib/prefab/periodic_sync.rb +30 -13
  21. data/lib/prefab/rate_limit_cache.rb +41 -0
  22. data/lib/prefab/resolved_config_presenter.rb +2 -4
  23. data/lib/prefab/weighted_value_resolver.rb +1 -1
  24. data/lib/prefab-cloud-ruby.rb +5 -5
  25. data/lib/prefab_pb.rb +11 -1
  26. data/prefab-cloud-ruby.gemspec +14 -9
  27. data/test/integration_test.rb +1 -3
  28. data/test/integration_test_helpers.rb +0 -1
  29. data/test/support/common_helpers.rb +174 -0
  30. data/test/support/mock_base_client.rb +44 -0
  31. data/test/support/mock_config_client.rb +19 -0
  32. data/test/support/mock_config_loader.rb +1 -0
  33. data/test/test_client.rb +354 -40
  34. data/test/test_config_client.rb +1 -0
  35. data/test/test_config_loader.rb +1 -0
  36. data/test/test_config_resolver.rb +25 -24
  37. data/test/test_config_value_unwrapper.rb +22 -32
  38. data/test/test_context.rb +1 -0
  39. data/test/test_context_shape_aggregator.rb +11 -1
  40. data/test/test_criteria_evaluator.rb +180 -133
  41. data/test/test_evaluation_summary_aggregator.rb +162 -0
  42. data/test/test_example_contexts_aggregator.rb +238 -0
  43. data/test/test_helper.rb +5 -131
  44. data/test/test_integration.rb +6 -4
  45. data/test/test_local_config_parser.rb +2 -2
  46. data/test/test_log_path_aggregator.rb +9 -1
  47. data/test/test_logger.rb +6 -5
  48. data/test/test_options.rb +33 -2
  49. data/test/test_rate_limit_cache.rb +44 -0
  50. data/test/test_weighted_value_resolver.rb +13 -7
  51. metadata +13 -8
  52. data/lib/prefab/evaluated_configs_aggregator.rb +0 -60
  53. data/lib/prefab/evaluated_keys_aggregator.rb +0 -41
  54. data/lib/prefab/noop_cache.rb +0 -15
  55. data/lib/prefab/noop_stats.rb +0 -8
  56. data/test/test_evaluated_configs_aggregator.rb +0 -254
  57. data/test/test_evaluated_keys_aggregator.rb +0 -54
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+ require 'timecop'
5
+
6
+ class RateLimitCacheTest < Minitest::Test
7
+ def test_set_and_fresh
8
+ cache = Prefab::RateLimitCache.new(5)
9
+ cache.set('key')
10
+ assert cache.fresh?('key')
11
+ end
12
+
13
+ def test_fresh_with_no_set
14
+ cache = Prefab::RateLimitCache.new(5)
15
+ refute cache.fresh?('key')
16
+ end
17
+
18
+ def test_get_after_expiration
19
+ cache = Prefab::RateLimitCache.new(5)
20
+
21
+ Timecop.freeze(Time.now - 6) do
22
+ cache.set('key')
23
+ assert cache.fresh?('key')
24
+ end
25
+
26
+ refute cache.fresh?('key')
27
+
28
+ # but the data is still there
29
+ assert cache.data.get('key')
30
+ end
31
+
32
+ def test_prune
33
+ cache = Prefab::RateLimitCache.new(5)
34
+
35
+ Timecop.freeze(Time.now - 6) do
36
+ cache.set('key')
37
+ assert cache.fresh?('key')
38
+ end
39
+
40
+ cache.prune
41
+
42
+ refute cache.fresh?('key')
43
+ end
44
+ end
@@ -8,30 +8,36 @@ class TestWeightedValueResolver < Minitest::Test
8
8
  def test_resolving_single_value
9
9
  values = weighted_values([['abc', 1]])
10
10
  resolver = Prefab::WeightedValueResolver.new(values, KEY, nil)
11
- assert_equal 'abc', resolver.resolve.value.string
11
+ assert_equal 'abc', resolver.resolve[0].value.string
12
+ assert_equal 0, resolver.resolve[1]
12
13
  end
13
14
 
14
15
  def test_resolving_multiple_values_evenly_distributed
15
16
  values = weighted_values([['abc', 1], ['def', 1]])
16
17
 
17
18
  resolver = Prefab::WeightedValueResolver.new(values, KEY, 'user:001')
18
- assert_equal 'abc', resolver.resolve.value.string
19
+ assert_equal 'abc', resolver.resolve[0].value.string
20
+ assert_equal 0, resolver.resolve[1]
19
21
 
20
22
  resolver = Prefab::WeightedValueResolver.new(values, KEY, 'user:456')
21
- assert_equal 'def', resolver.resolve.value.string
23
+ assert_equal 'def', resolver.resolve[0].value.string
24
+ assert_equal 1, resolver.resolve[1]
22
25
  end
23
26
 
24
27
  def test_resolving_multiple_values_unevenly_distributed
25
28
  values = weighted_values([['abc', 1], ['def', 98], ['ghi', 1]])
26
29
 
27
30
  resolver = Prefab::WeightedValueResolver.new(values, KEY, 'user:456')
28
- assert_equal 'def', resolver.resolve.value.string
31
+ assert_equal 'def', resolver.resolve[0].value.string
32
+ assert_equal 1, resolver.resolve[1]
29
33
 
30
34
  resolver = Prefab::WeightedValueResolver.new(values, KEY, 'user:103')
31
- assert_equal 'ghi', resolver.resolve.value.string
35
+ assert_equal 'ghi', resolver.resolve[0].value.string
36
+ assert_equal 2, resolver.resolve[1]
32
37
 
33
38
  resolver = Prefab::WeightedValueResolver.new(values, KEY, 'user:119')
34
- assert_equal 'abc', resolver.resolve.value.string
39
+ assert_equal 'abc', resolver.resolve[0].value.string
40
+ assert_equal 0, resolver.resolve[1]
35
41
  end
36
42
 
37
43
  def test_resolving_multiple_values_with_simulation
@@ -39,7 +45,7 @@ class TestWeightedValueResolver < Minitest::Test
39
45
  results = {}
40
46
 
41
47
  10_000.times do |i|
42
- result = Prefab::WeightedValueResolver.new(values, KEY, "user:#{i}").resolve.value.string
48
+ result = Prefab::WeightedValueResolver.new(values, KEY, "user:#{i}").resolve[0].value.string
43
49
  results[result] ||= 0
44
50
  results[result] += 1
45
51
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: prefab-cloud-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.24.5
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeff Dwyer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-07-10 00:00:00.000000000 Z
11
+ date: 2023-08-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -211,8 +211,9 @@ files:
211
211
  - lib/prefab/errors/initialization_timeout_error.rb
212
212
  - lib/prefab/errors/invalid_api_key_error.rb
213
213
  - lib/prefab/errors/missing_default_error.rb
214
- - lib/prefab/evaluated_configs_aggregator.rb
215
- - lib/prefab/evaluated_keys_aggregator.rb
214
+ - lib/prefab/evaluation.rb
215
+ - lib/prefab/evaluation_summary_aggregator.rb
216
+ - lib/prefab/example_contexts_aggregator.rb
216
217
  - lib/prefab/exponential_backoff.rb
217
218
  - lib/prefab/feature_flag_client.rb
218
219
  - lib/prefab/http_connection.rb
@@ -221,10 +222,9 @@ files:
221
222
  - lib/prefab/log_path_aggregator.rb
222
223
  - lib/prefab/logger_client.rb
223
224
  - lib/prefab/murmer3.rb
224
- - lib/prefab/noop_cache.rb
225
- - lib/prefab/noop_stats.rb
226
225
  - lib/prefab/options.rb
227
226
  - lib/prefab/periodic_sync.rb
227
+ - lib/prefab/rate_limit_cache.rb
228
228
  - lib/prefab/resolved_config_presenter.rb
229
229
  - lib/prefab/sse_logger.rb
230
230
  - lib/prefab/time_helpers.rb
@@ -236,6 +236,10 @@ files:
236
236
  - test/.prefab.unit_tests.config.yaml
237
237
  - test/integration_test.rb
238
238
  - test/integration_test_helpers.rb
239
+ - test/support/common_helpers.rb
240
+ - test/support/mock_base_client.rb
241
+ - test/support/mock_config_client.rb
242
+ - test/support/mock_config_loader.rb
239
243
  - test/test_client.rb
240
244
  - test/test_config_client.rb
241
245
  - test/test_config_loader.rb
@@ -245,8 +249,8 @@ files:
245
249
  - test/test_context_shape.rb
246
250
  - test/test_context_shape_aggregator.rb
247
251
  - test/test_criteria_evaluator.rb
248
- - test/test_evaluated_configs_aggregator.rb
249
- - test/test_evaluated_keys_aggregator.rb
252
+ - test/test_evaluation_summary_aggregator.rb
253
+ - test/test_example_contexts_aggregator.rb
250
254
  - test/test_exponential_backoff.rb
251
255
  - test/test_feature_flag_client.rb
252
256
  - test/test_helper.rb
@@ -255,6 +259,7 @@ files:
255
259
  - test/test_log_path_aggregator.rb
256
260
  - test/test_logger.rb
257
261
  - test/test_options.rb
262
+ - test/test_rate_limit_cache.rb
258
263
  - test/test_weighted_value_resolver.rb
259
264
  homepage: http://github.com/prefab-cloud/prefab-cloud-ruby
260
265
  licenses:
@@ -1,60 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'periodic_sync'
4
-
5
- module Prefab
6
- class EvaluatedConfigsAggregator
7
- include Prefab::PeriodicSync
8
-
9
- attr_reader :data
10
-
11
- def initialize(client:, max_configs:, sync_interval:)
12
- @max_configs = max_configs
13
- @client = client
14
- @name = 'evaluated_configs_aggregator'
15
-
16
- @data = Concurrent::Array.new
17
-
18
- start_periodic_sync(sync_interval)
19
- end
20
-
21
- def push(evaluation)
22
- return if @data.size >= @max_configs
23
-
24
- @data.push(evaluation)
25
- end
26
-
27
- def prepare_data
28
- to_ship = @data.dup
29
- @data.clear
30
-
31
- to_ship.map { |e| coerce_to_proto(e) }
32
- end
33
-
34
- def coerce_to_proto(evaluation)
35
- config, result, context = evaluation
36
-
37
- PrefabProto::EvaluatedConfig.new(
38
- key: config.key,
39
- config_version: config.id,
40
- result: result,
41
- context: context.to_proto(@client.namespace),
42
- timestamp: Prefab::TimeHelpers.now_in_ms
43
- )
44
- end
45
-
46
- private
47
-
48
- def flush(to_ship, _)
49
- @pool.post do
50
- log_internal "Uploading evaluated configs for #{to_ship.size}"
51
-
52
- configs = PrefabProto::EvaluatedConfigs.new(configs: to_ship)
53
-
54
- result = @client.post('/api/v1/evaluated-configs', configs)
55
-
56
- log_internal "Uploaded #{to_ship.size} configs: #{result.status}"
57
- end
58
- end
59
- end
60
- end
@@ -1,41 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'periodic_sync'
4
-
5
- module Prefab
6
- class EvaluatedKeysAggregator
7
- include Prefab::PeriodicSync
8
-
9
- attr_reader :data
10
-
11
- def initialize(client:, max_keys:, sync_interval:)
12
- @max_keys = max_keys
13
- @client = client
14
- @name = 'evaluated_keys_aggregator'
15
-
16
- @data = Concurrent::Set.new
17
-
18
- start_periodic_sync(sync_interval)
19
- end
20
-
21
- def push(key)
22
- return if @data.size >= @max_keys
23
-
24
- @data.add(key)
25
- end
26
-
27
- private
28
-
29
- def flush(to_ship, _)
30
- @pool.post do
31
- log_internal "Uploading evaluated keys for #{to_ship.size}"
32
-
33
- keys = PrefabProto::EvaluatedKeys.new(keys: to_ship.to_a, namespace: @client.namespace)
34
-
35
- result = @client.post('/api/v1/evaluated-keys', keys)
36
-
37
- log_internal "Uploaded #{to_ship.size} keys: #{result.status}"
38
- end
39
- end
40
- end
41
- end
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Prefab
4
- class NoopCache
5
- def fetch(_name, _opts)
6
- yield
7
- end
8
-
9
- def write(name, value, opts = nil); end
10
-
11
- def read(name); end
12
-
13
- def delete(name); end
14
- end
15
- end
@@ -1,8 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Prefab
4
- class NoopStats
5
- # receives increment("prefab.ratelimit.limitcheck", {:tags=>["policy_group:page_view", "pass:true"]})
6
- def increment(name, opts = {}); end
7
- end
8
- end
@@ -1,254 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'test_helper'
4
- require 'timecop'
5
-
6
- class TestEvaluatedConfigsAggregator < Minitest::Test
7
- MAX_WAIT = 2
8
- SLEEP_TIME = 0.01
9
-
10
- def test_push
11
- aggregator = Prefab::EvaluatedConfigsAggregator.new(client: new_client, max_configs: 2, sync_interval: 1000)
12
-
13
- aggregator.push([])
14
- aggregator.push([])
15
-
16
- assert_equal 2, aggregator.data.size
17
-
18
- # we've reached the limit, so no more
19
- aggregator.push([])
20
- assert_equal 2, aggregator.data.size
21
- end
22
-
23
- def test_coerce_to_proto
24
- aggregator = Prefab::EvaluatedConfigsAggregator.new(client: new_client, max_configs: 2, sync_interval: 2)
25
-
26
- Timecop.freeze do
27
- coerced = aggregator.coerce_to_proto([
28
- CONFIG_1,
29
- DESIRED_VALUE,
30
- Prefab::Context.new(CONTEXT)
31
- ])
32
-
33
- assert_equal PrefabProto::EvaluatedConfig.new(
34
- key: CONFIG_1.key,
35
- config_version: CONFIG_1.id,
36
- result: DESIRED_VALUE,
37
- context: PrefabProto::ContextSet.new(
38
- contexts: [
39
- PrefabProto::Context.new(
40
- type: "user",
41
- values: {
42
- "id" => PrefabProto::ConfigValue.new(int: 1),
43
- "email_suffix" => PrefabProto::ConfigValue.new(string: "hotmail.com")
44
- }
45
- ),
46
- PrefabProto::Context.new(
47
- type: "team",
48
- values: {
49
- "id" => PrefabProto::ConfigValue.new(int: 2),
50
- "name" => PrefabProto::ConfigValue.new(string: "team-name")
51
- }
52
- ),
53
- PrefabProto::Context.new(
54
- type: "prefab",
55
- values: {
56
- "current-time" => PrefabProto::ConfigValue.new(int: Prefab::TimeHelpers.now_in_ms),
57
- }
58
- ),
59
- ]
60
- ),
61
- timestamp: Prefab::TimeHelpers.now_in_ms
62
- ), coerced
63
- end
64
- end
65
-
66
- def test_sync
67
- client = new_client(namespace: 'this.is.a.namespace')
68
-
69
- inject_config(client, CONFIG_1)
70
- inject_config(client, CONFIG_2)
71
- inject_project_env_id(client, PROJECT_ENV_ID)
72
-
73
- client.get CONFIG_1.key, 'default', CONTEXT
74
- client.get CONFIG_1.key, 'default', { user: { email_suffix: "example.com" }, device: { mobile: true } }
75
- client.get CONFIG_2.key, 'default', CONTEXT
76
-
77
- # logger items are not reported
78
- client.get "#{Prefab::ConfigClient::LOGGING_KEY_PREFIX}something", 'default', CONTEXT
79
- client.get "#{Prefab::LoggerClient::BASE_KEY}", 'default', CONTEXT
80
-
81
- requests = wait_for_post_requests(client) do
82
- client.evaluated_configs_aggregator.send(:sync)
83
- end
84
-
85
- assert_equal [[
86
- '/api/v1/evaluated-configs',
87
- PrefabProto::EvaluatedConfigs.new(
88
- configs: [
89
- PrefabProto::EvaluatedConfig.new(
90
- key: CONFIG_1.key,
91
- config_version: CONFIG_1.id,
92
- result: DESIRED_VALUE,
93
- context: PrefabProto::ContextSet.new(
94
- contexts: [
95
- PrefabProto::Context.new(
96
- type: "user",
97
- values: {
98
- "id" => PrefabProto::ConfigValue.new(int: 1),
99
- "email_suffix" => PrefabProto::ConfigValue.new(string: "hotmail.com")
100
- }
101
- ),
102
- PrefabProto::Context.new(
103
- type: "team",
104
- values: {
105
- "id" => PrefabProto::ConfigValue.new(int: 2),
106
- "name" => PrefabProto::ConfigValue.new(string: "team-name")
107
- }
108
- ),
109
- PrefabProto::Context.new(
110
- type: "prefab",
111
- values: {
112
- "current-time" => PrefabProto::ConfigValue.new(int: Prefab::TimeHelpers.now_in_ms),
113
- "namespace" => PrefabProto::ConfigValue.new(string: "this.is.a.namespace"),
114
- }
115
- ),
116
- ]
117
- ),
118
- timestamp: Prefab::TimeHelpers.now_in_ms
119
- ),
120
- PrefabProto::EvaluatedConfig.new(
121
- key: CONFIG_1.key,
122
- config_version: CONFIG_1.id,
123
- result: DEFAULT_VALUE,
124
- context: PrefabProto::ContextSet.new(
125
- contexts: [
126
- PrefabProto::Context.new(
127
- type: "user",
128
- values: {
129
- "email_suffix" => PrefabProto::ConfigValue.new(string: "example.com")
130
- }
131
- ),
132
- PrefabProto::Context.new(
133
- type: "device",
134
- values: {
135
- "mobile" => PrefabProto::ConfigValue.new(bool: true),
136
- }
137
- ),
138
- PrefabProto::Context.new(
139
- type: "prefab",
140
- values: {
141
- "current-time" => PrefabProto::ConfigValue.new(int: Prefab::TimeHelpers.now_in_ms),
142
- "namespace" => PrefabProto::ConfigValue.new(string: "this.is.a.namespace"),
143
- }
144
- )
145
-
146
- ]
147
- ),
148
- timestamp: Prefab::TimeHelpers.now_in_ms
149
- ),
150
-
151
- PrefabProto::EvaluatedConfig.new(
152
- key: CONFIG_2.key,
153
- config_version: CONFIG_2.id,
154
- result: DEFAULT_VALUE,
155
- context: PrefabProto::ContextSet.new(
156
- contexts: [
157
- PrefabProto::Context.new(
158
- type: "user",
159
- values: {
160
- "id" => PrefabProto::ConfigValue.new(int: 1),
161
- "email_suffix" => PrefabProto::ConfigValue.new(string: "hotmail.com")
162
- }
163
- ),
164
- PrefabProto::Context.new(
165
- type: "team",
166
- values: {
167
- "id" => PrefabProto::ConfigValue.new(int: 2),
168
- "name" => PrefabProto::ConfigValue.new(string: "team-name")
169
- }
170
- ),
171
- PrefabProto::Context.new(
172
- type: "prefab",
173
- values: {
174
- "current-time" => PrefabProto::ConfigValue.new(int: Prefab::TimeHelpers.now_in_ms),
175
- "namespace" => PrefabProto::ConfigValue.new(string: "this.is.a.namespace"),
176
- }
177
- )
178
- ]
179
- ),
180
- timestamp: Prefab::TimeHelpers.now_in_ms
181
- )
182
-
183
- ]
184
- )
185
- ]], requests
186
- end
187
-
188
- private
189
-
190
- def new_client(overrides = {})
191
- super(**{
192
- prefab_datasources: Prefab::Options::DATASOURCES::ALL,
193
- initialization_timeout_sec: 0,
194
- on_init_failure: Prefab::Options::ON_INITIALIZATION_FAILURE::RETURN,
195
- api_key: '123-development-yourapikey-SDK',
196
- collect_sync_interval: 1000, # we'll trigger sync manually in our test
197
- collect_evaluations: true
198
- }.merge(overrides))
199
- end
200
-
201
- DEFAULT_VALUE = PrefabProto::ConfigValue.new(string: '❌')
202
-
203
- DESIRED_VALUE = PrefabProto::ConfigValue.new(string: "✅")
204
-
205
- DEFAULT_ROW = PrefabProto::ConfigRow.new(
206
- values: [
207
- PrefabProto::ConditionalValue.new(
208
- value: DEFAULT_VALUE
209
- )
210
- ]
211
- )
212
-
213
- PROJECT_ENV_ID = 1
214
-
215
- CONFIG_1 = PrefabProto::Config.new(
216
- id: 1,
217
- key: "key.1",
218
- rows: [
219
- PrefabProto::ConfigRow.new(
220
- project_env_id: PROJECT_ENV_ID,
221
- values: [
222
- PrefabProto::ConditionalValue.new(
223
- criteria: [
224
- PrefabProto::Criterion.new(
225
- operator: PrefabProto::Criterion::CriterionOperator::PROP_IS_ONE_OF,
226
- value_to_match: string_list(['hotmail.com', 'gmail.com']),
227
- property_name: 'user.email_suffix'
228
- )
229
- ],
230
- value: DESIRED_VALUE
231
- )
232
- ]
233
- ),
234
- DEFAULT_ROW
235
- ]
236
- )
237
-
238
- CONFIG_2 = PrefabProto::Config.new(
239
- id: 2,
240
- key: "key.2",
241
- rows: [DEFAULT_ROW,]
242
- )
243
-
244
- CONTEXT = {
245
- user: {
246
- id: 1,
247
- email_suffix: 'hotmail.com'
248
- },
249
- team: {
250
- id: 2,
251
- name: 'team-name'
252
- }
253
- }
254
- end
@@ -1,54 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'test_helper'
4
-
5
- class TestEvaluatedKeysAggregator < Minitest::Test
6
- MAX_WAIT = 2
7
- SLEEP_TIME = 0.01
8
-
9
- def test_push
10
- aggregator = Prefab::EvaluatedKeysAggregator.new(client: new_client, max_keys: 2, sync_interval: 1000)
11
-
12
- aggregator.push('key.1')
13
- aggregator.push('key.2')
14
-
15
- assert_equal 2, aggregator.data.size
16
-
17
- # we've reached the limit, so no more
18
- aggregator.push('key.3')
19
- assert_equal 2, aggregator.data.size
20
- end
21
-
22
- def test_sync
23
- client = new_client(namespace: 'this.is.a.namespace')
24
-
25
- client.get 'key.1', 'default', {}
26
- client.get 'key.1', 'default', {}
27
- client.get 'key.2', 'default', {}
28
-
29
- requests = wait_for_post_requests(client) do
30
- client.evaluated_keys_aggregator.send(:sync)
31
- end
32
-
33
- assert_equal [[
34
- '/api/v1/evaluated-keys',
35
- PrefabProto::EvaluatedKeys.new(
36
- keys: ['key.1', 'key.2'],
37
- namespace: 'this.is.a.namespace'
38
- )
39
- ]], requests
40
- end
41
-
42
- private
43
-
44
- def new_client(overrides = {})
45
- super(**{
46
- prefab_datasources: Prefab::Options::DATASOURCES::ALL,
47
- initialization_timeout_sec: 0,
48
- on_init_failure: Prefab::Options::ON_INITIALIZATION_FAILURE::RETURN,
49
- api_key: '123-development-yourapikey-SDK',
50
- collect_sync_interval: 1000, # we'll trigger sync manually in our test
51
- collect_keys: true
52
- }.merge(overrides))
53
- end
54
- end