prefab-cloud-ruby 0.20.0 → 0.22.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 (56) hide show
  1. checksums.yaml +4 -4
  2. data/.envrc.sample +3 -0
  3. data/.github/workflows/ruby.yml +5 -1
  4. data/.gitmodules +3 -0
  5. data/Gemfile +14 -12
  6. data/Gemfile.lock +24 -14
  7. data/README.md +12 -10
  8. data/Rakefile +13 -14
  9. data/VERSION +1 -1
  10. data/lib/prefab/auth_interceptor.rb +2 -1
  11. data/lib/prefab/cancellable_interceptor.rb +8 -7
  12. data/lib/prefab/client.rb +52 -27
  13. data/lib/prefab/config_client.rb +59 -70
  14. data/lib/prefab/config_loader.rb +7 -114
  15. data/lib/prefab/config_resolver.rb +27 -57
  16. data/lib/prefab/config_value_unwrapper.rb +23 -0
  17. data/lib/prefab/criteria_evaluator.rb +96 -0
  18. data/lib/prefab/errors/invalid_api_key_error.rb +1 -1
  19. data/lib/prefab/feature_flag_client.rb +13 -145
  20. data/lib/prefab/internal_logger.rb +7 -6
  21. data/lib/prefab/local_config_parser.rb +110 -0
  22. data/lib/prefab/log_path_collector.rb +98 -0
  23. data/lib/prefab/logger_client.rb +46 -44
  24. data/lib/prefab/murmer3.rb +3 -4
  25. data/lib/prefab/noop_cache.rb +5 -7
  26. data/lib/prefab/noop_stats.rb +2 -3
  27. data/lib/prefab/options.rb +32 -11
  28. data/lib/prefab/ratelimit_client.rb +11 -13
  29. data/lib/prefab/sse_logger.rb +3 -2
  30. data/lib/prefab/weighted_value_resolver.rb +42 -0
  31. data/lib/prefab/yaml_config_parser.rb +32 -0
  32. data/lib/prefab-cloud-ruby.rb +7 -2
  33. data/lib/prefab_pb.rb +70 -43
  34. data/lib/prefab_services_pb.rb +14 -1
  35. data/prefab-cloud-ruby.gemspec +33 -19
  36. data/test/.prefab.unit_tests.config.yaml +3 -2
  37. data/test/integration_test.rb +98 -0
  38. data/test/integration_test_helpers.rb +37 -0
  39. data/test/test_client.rb +56 -31
  40. data/test/test_config_client.rb +21 -20
  41. data/test/test_config_loader.rb +48 -37
  42. data/test/test_config_resolver.rb +312 -135
  43. data/test/test_config_value_unwrapper.rb +83 -0
  44. data/test/test_criteria_evaluator.rb +533 -0
  45. data/test/test_feature_flag_client.rb +35 -347
  46. data/test/test_helper.rb +18 -14
  47. data/test/test_integration.rb +33 -0
  48. data/test/test_local_config_parser.rb +78 -0
  49. data/test/test_log_path_collector.rb +56 -0
  50. data/test/test_logger.rb +52 -51
  51. data/test/test_options.rb +32 -0
  52. data/test/test_weighted_value_resolver.rb +65 -0
  53. metadata +30 -16
  54. data/lib/prefab/config_helper.rb +0 -31
  55. data/run_test_harness_server.sh +0 -8
  56. data/test/harness_server.rb +0 -64
data/test/test_logger.rb CHANGED
@@ -11,19 +11,19 @@ class TestCLogger < Minitest::Test
11
11
  end
12
12
 
13
13
  def test_get_path
14
- assert_equal "test_l.foo_warn",
15
- @logger.get_path("/Users/jdwyah/Documents/workspace/RateLimitInc/prefab-cloud-ruby/lib/test_l.rb",
16
- "foo_warn")
17
-
18
- assert_equal "active_support.log_subscriber.info",
19
- @logger.get_path("/Users/jdwyah/.rvm/gems/ruby-2.3.3@forcerank/gems/activesupport-4.1.16/lib/active_support/log_subscriber.rb",
20
- "info")
21
- assert_equal "active_support.log_subscriber.info",
14
+ assert_equal 'test_l.foo_warn',
15
+ @logger.get_path('/Users/jdwyah/Documents/workspace/RateLimitInc/prefab-cloud-ruby/lib/test_l.rb',
16
+ 'foo_warn')
17
+
18
+ assert_equal 'active_support.log_subscriber.info',
19
+ @logger.get_path('/Users/jdwyah/.rvm/gems/ruby-2.3.3@forcerank/gems/activesupport-4.1.16/lib/active_support/log_subscriber.rb',
20
+ 'info')
21
+ assert_equal 'active_support.log_subscriber.info',
22
22
  @logger.get_path("/Users/jeffdwyer/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/activesupport-7.0.2.4/lib/active_support/log_subscriber.rb:130:in `info'",
23
- "info")
24
- assert_equal "unknown.info",
23
+ 'info')
24
+ assert_equal 'unknown.info',
25
25
  @logger.get_path(nil,
26
- "info")
26
+ 'info')
27
27
  end
28
28
 
29
29
  def test_loc_resolution
@@ -34,80 +34,81 @@ class TestCLogger < Minitest::Test
34
34
  end # https://ruby-doc.org/core-3.0.0/Thread/Backtrace/Location.html
35
35
 
36
36
  # verify that even if the Thread::Backtrace::Location does not have an absolute_location, we do our best
37
- assert_equal "active_support.log_subscriber.info",
37
+ assert_equal 'active_support.log_subscriber.info',
38
38
  @logger.get_loc_path(backtrace_location.new(nil,
39
- "info",
39
+ 'info',
40
40
  "/Users/jeffdwyer/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/activesupport-7.0.2.4/lib/active_support/log_subscriber.rb:130:in `info'"))
41
- assert_equal "test_l.info",
42
- @logger.get_loc_path(backtrace_location.new("/Users/jdwyah/Documents/workspace/RateLimitInc/prefab-cloud-ruby/lib/test_l.rb",
43
- "info",
41
+ assert_equal 'test_l.info',
42
+ @logger.get_loc_path(backtrace_location.new('/Users/jdwyah/Documents/workspace/RateLimitInc/prefab-cloud-ruby/lib/test_l.rb',
43
+ 'info',
44
44
  "/Users/jeffdwyer/.asdf/installs/ruby/3.1.2/lib/ruby/gems/3.1.0/gems/activesupport-7.0.2.4/lib/active_support/log_subscriber.rb:130:in `info'"))
45
45
  end
46
46
 
47
47
  def test_level_of
48
- with_env("PREFAB_LOG_CLIENT_BOOTSTRAP_LOG_LEVEL", "info") do
48
+ with_env('PREFAB_LOG_CLIENT_BOOTSTRAP_LOG_LEVEL', 'info') do
49
49
  # env var overrides the default level
50
- assert_equal Logger::INFO,
51
- @logger.level_of("app.models.user"), "PREFAB_LOG_CLIENT_BOOTSTRAP_LOG_LEVEL is info"
50
+ assert_equal ::Logger::INFO,
51
+ @logger.level_of('app.models.user'), 'PREFAB_LOG_CLIENT_BOOTSTRAP_LOG_LEVEL is info'
52
52
 
53
53
  @logger.set_config_client(MockConfigClient.new({}))
54
- assert_equal Logger::WARN,
55
- @logger.level_of("app.models.user"), "default is warn"
54
+ assert_equal ::Logger::WARN,
55
+ @logger.level_of('app.models.user'), 'default is warn'
56
56
 
57
- @logger.set_config_client(MockConfigClient.new("log-level.app" => :INFO))
58
- assert_equal Logger::INFO,
59
- @logger.level_of("app.models.user")
57
+ @logger.set_config_client(MockConfigClient.new('log-level.app' => :INFO))
58
+ assert_equal ::Logger::INFO,
59
+ @logger.level_of('app.models.user')
60
60
 
61
- @logger.set_config_client(MockConfigClient.new("log-level.app" => :DEBUG))
62
- assert_equal Logger::DEBUG,
63
- @logger.level_of("app.models.user")
61
+ @logger.set_config_client(MockConfigClient.new('log-level.app' => :DEBUG))
62
+ assert_equal ::Logger::DEBUG,
63
+ @logger.level_of('app.models.user')
64
64
 
65
- @logger.set_config_client(MockConfigClient.new("log-level.app" => :DEBUG,
66
- "log-level.app.models" => :ERROR))
67
- assert_equal Logger::ERROR,
68
- @logger.level_of("app.models.user"), "test leveling"
65
+ @logger.set_config_client(MockConfigClient.new('log-level.app' => :DEBUG,
66
+ 'log-level.app.models' => :ERROR))
67
+ assert_equal ::Logger::ERROR,
68
+ @logger.level_of('app.models.user'), 'test leveling'
69
69
  end
70
70
  end
71
71
 
72
72
  def test_log_internal
73
73
  logger, mock_logdev = mock_logger_expecting(/W, \[.*\] WARN -- cloud.prefab.client.test.path: : test message/)
74
- logger.log_internal("test message", "test.path", "", Logger::WARN)
74
+ logger.log_internal('test message', 'test.path', '', ::Logger::WARN)
75
75
  mock_logdev.verify
76
76
  end
77
77
 
78
78
  def test_log_internal_unknown
79
79
  logger, mock_logdev = mock_logger_expecting(/A, \[.*\] ANY -- cloud.prefab.client.test.path: : test message/)
80
- logger.log_internal("test message", "test.path", "", Logger::UNKNOWN)
80
+ logger.log_internal('test message', 'test.path', '', ::Logger::UNKNOWN)
81
81
  mock_logdev.verify
82
82
  end
83
83
 
84
84
  def test_log_internal_silencing
85
- logger, mock_logdev = mock_logger_expecting(/W, \[.*\] WARN -- cloud.prefab.client.test.path: : should log/, calls: 2)
85
+ logger, mock_logdev = mock_logger_expecting(/W, \[.*\] WARN -- cloud.prefab.client.test.path: : should log/,
86
+ calls: 2)
86
87
  logger.silence do
87
- logger.log_internal("should not log", "test.path", "", Logger::WARN)
88
+ logger.log_internal('should not log', 'test.path', '', ::Logger::WARN)
88
89
  end
89
- logger.log_internal("should log", "test.path", "", Logger::WARN)
90
+ logger.log_internal('should log', 'test.path', '', ::Logger::WARN)
90
91
  mock_logdev.verify
91
92
  end
92
93
 
93
94
  def test_log
94
95
  logger, mock_logdev = mock_logger_expecting(/W, \[.*\] WARN -- test.path: : test message/)
95
- logger.log("test message", "test.path", "", Logger::WARN)
96
+ logger.log('test message', 'test.path', '', ::Logger::WARN)
96
97
  mock_logdev.verify
97
98
  end
98
99
 
99
100
  def test_log_unknown
100
101
  logger, mock_logdev = mock_logger_expecting(/A, \[.*\] ANY -- test.path: : test message/)
101
- logger.log("test message", "test.path", "", Logger::UNKNOWN)
102
+ logger.log('test message', 'test.path', '', ::Logger::UNKNOWN)
102
103
  mock_logdev.verify
103
104
  end
104
105
 
105
106
  def test_log_silencing
106
107
  logger, mock_logdev = mock_logger_expecting(/W, \[.*\] WARN -- test.path: : should log/, calls: 2)
107
108
  logger.silence do
108
- logger.log("should not log", "test.path", "", Logger::WARN)
109
+ logger.log('should not log', 'test.path', '', ::Logger::WARN)
109
110
  end
110
- logger.log("should log", "test.path", "", Logger::WARN)
111
+ logger.log('should log', 'test.path', '', ::Logger::WARN)
111
112
  mock_logdev.verify
112
113
  end
113
114
 
@@ -125,11 +126,11 @@ class TestCLogger < Minitest::Test
125
126
 
126
127
  def test_logging_without_a_progname
127
128
  prefab, io = captured_logger
128
- message = "MY MESSAGE"
129
+ message = 'MY MESSAGE'
129
130
 
130
131
  prefab.log.error message
131
132
 
132
- assert_logged io, 'ERROR', "test.test_logger.test_logging_without_a_progname", message
133
+ assert_logged io, 'ERROR', 'test.test_logger.test_logging_without_a_progname', message
133
134
  end
134
135
 
135
136
  def test_logging_without_a_progname_or_message
@@ -137,35 +138,35 @@ class TestCLogger < Minitest::Test
137
138
 
138
139
  prefab.log.error
139
140
 
140
- assert_logged io, 'ERROR', "test.test_logger.test_logging_without_a_progname_or_message", ""
141
+ assert_logged io, 'ERROR', 'test.test_logger.test_logging_without_a_progname_or_message', ''
141
142
  end
142
143
 
143
144
  def test_logging_with_a_progname
144
145
  prefab, io = captured_logger
145
- message = "MY MESSAGE"
146
+ message = 'MY MESSAGE'
146
147
 
147
- prefab.log.progname = "MY_PROGNAME"
148
+ prefab.log.progname = 'MY_PROGNAME'
148
149
  prefab.log.error message
149
150
 
150
- assert_logged io, 'ERROR', "MY_PROGNAME test.test_logger.test_logging_with_a_progname", message
151
+ assert_logged io, 'ERROR', 'MY_PROGNAME test.test_logger.test_logging_with_a_progname', message
151
152
  end
152
153
 
153
154
  def test_logging_with_a_progname_and_no_message
154
155
  prefab, io = captured_logger
155
156
 
156
- prefab.log.progname = "MY_PROGNAME"
157
+ prefab.log.progname = 'MY_PROGNAME'
157
158
  prefab.log.error
158
159
 
159
- assert_logged io, 'ERROR', "MY_PROGNAME test.test_logger.test_logging_with_a_progname_and_no_message", "MY_PROGNAME"
160
+ assert_logged io, 'ERROR', 'MY_PROGNAME test.test_logger.test_logging_with_a_progname_and_no_message', 'MY_PROGNAME'
160
161
  end
161
162
 
162
163
  private
163
164
 
164
165
  def assert_logged(logged_io, level, path, message)
165
- assert_match(/#{level} \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [-\+]?\d+: #{path}: #{message}\n/, logged_io.string)
166
+ assert_match(/#{level} \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [-+]?\d+: #{path}: #{message}\n/, logged_io.string)
166
167
  end
167
168
 
168
- def mock_logger_expecting pattern, configs = {}, calls: 1
169
+ def mock_logger_expecting(pattern, configs = {}, calls: 1)
169
170
  mock_logdev = Minitest::Mock.new
170
171
  mock_logdev.expect :write, nil do |arg|
171
172
  pattern.match(arg)
@@ -189,6 +190,6 @@ class TestCLogger < Minitest::Test
189
190
  ))
190
191
  prefab = Prefab::Client.new(options)
191
192
 
192
- return [prefab, io]
193
+ [prefab, io]
193
194
  end
194
195
  end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ class TestOptions < Minitest::Test
6
+ API_KEY = 'abcdefg'
7
+
8
+ def test_works_with_named_arguments
9
+ assert_equal API_KEY, Prefab::Options.new(api_key: API_KEY).api_key
10
+ end
11
+
12
+ def test_works_with_hash
13
+ assert_equal API_KEY, Prefab::Options.new({ api_key: API_KEY }).api_key
14
+ end
15
+
16
+ def test_collect_max_paths
17
+ assert_equal 1000, Prefab::Options.new.collect_max_paths
18
+ assert_equal 100, Prefab::Options.new(collect_max_paths: 100).collect_max_paths
19
+ end
20
+
21
+ def test_collect_max_paths_with_local_only
22
+ options = Prefab::Options.new(collect_max_paths: 100,
23
+ prefab_datasources: Prefab::Options::DATASOURCES::LOCAL_ONLY)
24
+ assert_equal 0, options.collect_max_paths
25
+ end
26
+
27
+ def test_collect_max_paths_with_collect_logs_false
28
+ options = Prefab::Options.new(collect_max_paths: 100,
29
+ collect_logs: false)
30
+ assert_equal 0, options.collect_max_paths
31
+ end
32
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'test_helper'
4
+
5
+ class TestWeightedValueResolver < Minitest::Test
6
+ KEY = 'config_key'
7
+
8
+ def test_resolving_single_value
9
+ values = weighted_values([['abc', 1]])
10
+ resolver = Prefab::WeightedValueResolver.new(values, KEY, nil)
11
+ assert_equal 'abc', resolver.resolve.value.string
12
+ end
13
+
14
+ def test_resolving_multiple_values_evenly_distributed
15
+ values = weighted_values([['abc', 1], ['def', 1]])
16
+
17
+ resolver = Prefab::WeightedValueResolver.new(values, KEY, 'user:001')
18
+ assert_equal 'abc', resolver.resolve.value.string
19
+
20
+ resolver = Prefab::WeightedValueResolver.new(values, KEY, 'user:456')
21
+ assert_equal 'def', resolver.resolve.value.string
22
+ end
23
+
24
+ def test_resolving_multiple_values_unevenly_distributed
25
+ values = weighted_values([['abc', 1], ['def', 98], ['ghi', 1]])
26
+
27
+ resolver = Prefab::WeightedValueResolver.new(values, KEY, 'user:456')
28
+ assert_equal 'def', resolver.resolve.value.string
29
+
30
+ resolver = Prefab::WeightedValueResolver.new(values, KEY, 'user:103')
31
+ assert_equal 'ghi', resolver.resolve.value.string
32
+
33
+ resolver = Prefab::WeightedValueResolver.new(values, KEY, 'user:119')
34
+ assert_equal 'abc', resolver.resolve.value.string
35
+ end
36
+
37
+ def test_resolving_multiple_values_with_simulation
38
+ values = weighted_values([['abc', 1], ['def', 98], ['ghi', 1]])
39
+ results = {}
40
+
41
+ 10_000.times do |i|
42
+ result = Prefab::WeightedValueResolver.new(values, KEY, "user:#{i}").resolve.value.string
43
+ results[result] ||= 0
44
+ results[result] += 1
45
+ end
46
+
47
+ assert_in_delta 100, results['abc'], 20
48
+ assert_in_delta 9800, results['def'], 50
49
+ assert_in_delta 100, results['ghi'], 20
50
+ end
51
+
52
+ private
53
+
54
+ def weighted_values(values_and_weights)
55
+ values_and_weights.map do |value, weight|
56
+ weighted_value(value, weight)
57
+ end
58
+ end
59
+
60
+ def weighted_value(string, weight)
61
+ Prefab::WeightedValue.new(
62
+ value: Prefab::ConfigValue.new(string: string), weight: weight
63
+ )
64
+ end
65
+ 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.20.0
4
+ version: 0.22.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: 2022-12-02 00:00:00.000000000 Z
11
+ date: 2023-03-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -45,7 +45,7 @@ dependencies:
45
45
  - !ruby/object:Gem::Version
46
46
  version: '0'
47
47
  - !ruby/object:Gem::Dependency
48
- name: ld-eventsource
48
+ name: googleapis-common-protos-types
49
49
  requirement: !ruby/object:Gem::Requirement
50
50
  requirements:
51
51
  - - ">="
@@ -59,7 +59,7 @@ dependencies:
59
59
  - !ruby/object:Gem::Version
60
60
  version: '0'
61
61
  - !ruby/object:Gem::Dependency
62
- name: grpc
62
+ name: google-protobuf
63
63
  requirement: !ruby/object:Gem::Requirement
64
64
  requirements:
65
65
  - - ">="
@@ -73,7 +73,7 @@ dependencies:
73
73
  - !ruby/object:Gem::Version
74
74
  version: '0'
75
75
  - !ruby/object:Gem::Dependency
76
- name: google-protobuf
76
+ name: grpc
77
77
  requirement: !ruby/object:Gem::Requirement
78
78
  requirements:
79
79
  - - ">="
@@ -87,7 +87,7 @@ dependencies:
87
87
  - !ruby/object:Gem::Version
88
88
  version: '0'
89
89
  - !ruby/object:Gem::Dependency
90
- name: googleapis-common-protos-types
90
+ name: ld-eventsource
91
91
  requirement: !ruby/object:Gem::Requirement
92
92
  requirements:
93
93
  - - ">="
@@ -101,13 +101,13 @@ dependencies:
101
101
  - !ruby/object:Gem::Version
102
102
  version: '0'
103
103
  - !ruby/object:Gem::Dependency
104
- name: benchmark-ips
104
+ name: uuid
105
105
  requirement: !ruby/object:Gem::Requirement
106
106
  requirements:
107
107
  - - ">="
108
108
  - !ruby/object:Gem::Version
109
109
  version: '0'
110
- type: :development
110
+ type: :runtime
111
111
  prerelease: false
112
112
  version_requirements: !ruby/object:Gem::Requirement
113
113
  requirements:
@@ -115,7 +115,7 @@ dependencies:
115
115
  - !ruby/object:Gem::Version
116
116
  version: '0'
117
117
  - !ruby/object:Gem::Dependency
118
- name: grpc-tools
118
+ name: benchmark-ips
119
119
  requirement: !ruby/object:Gem::Requirement
120
120
  requirements:
121
121
  - - ">="
@@ -129,7 +129,7 @@ dependencies:
129
129
  - !ruby/object:Gem::Version
130
130
  version: '0'
131
131
  - !ruby/object:Gem::Dependency
132
- name: rdoc
132
+ name: bundler
133
133
  requirement: !ruby/object:Gem::Requirement
134
134
  requirements:
135
135
  - - ">="
@@ -143,7 +143,7 @@ dependencies:
143
143
  - !ruby/object:Gem::Version
144
144
  version: '0'
145
145
  - !ruby/object:Gem::Dependency
146
- name: bundler
146
+ name: grpc-tools
147
147
  requirement: !ruby/object:Gem::Requirement
148
148
  requirements:
149
149
  - - ">="
@@ -171,7 +171,7 @@ dependencies:
171
171
  - !ruby/object:Gem::Version
172
172
  version: 2.4.9
173
173
  - !ruby/object:Gem::Dependency
174
- name: simplecov
174
+ name: rdoc
175
175
  requirement: !ruby/object:Gem::Requirement
176
176
  requirements:
177
177
  - - ">="
@@ -185,7 +185,7 @@ dependencies:
185
185
  - !ruby/object:Gem::Version
186
186
  version: '0'
187
187
  - !ruby/object:Gem::Dependency
188
- name: thin
188
+ name: simplecov
189
189
  requirement: !ruby/object:Gem::Requirement
190
190
  requirements:
191
191
  - - ">="
@@ -207,7 +207,9 @@ extra_rdoc_files:
207
207
  - README.md
208
208
  files:
209
209
  - ".envrc"
210
+ - ".envrc.sample"
210
211
  - ".github/workflows/ruby.yml"
212
+ - ".gitmodules"
211
213
  - ".tool-versions"
212
214
  - CODEOWNERS
213
215
  - Gemfile
@@ -222,15 +224,18 @@ files:
222
224
  - lib/prefab/cancellable_interceptor.rb
223
225
  - lib/prefab/client.rb
224
226
  - lib/prefab/config_client.rb
225
- - lib/prefab/config_helper.rb
226
227
  - lib/prefab/config_loader.rb
227
228
  - lib/prefab/config_resolver.rb
229
+ - lib/prefab/config_value_unwrapper.rb
230
+ - lib/prefab/criteria_evaluator.rb
228
231
  - lib/prefab/error.rb
229
232
  - lib/prefab/errors/initialization_timeout_error.rb
230
233
  - lib/prefab/errors/invalid_api_key_error.rb
231
234
  - lib/prefab/errors/missing_default_error.rb
232
235
  - lib/prefab/feature_flag_client.rb
233
236
  - lib/prefab/internal_logger.rb
237
+ - lib/prefab/local_config_parser.rb
238
+ - lib/prefab/log_path_collector.rb
234
239
  - lib/prefab/logger_client.rb
235
240
  - lib/prefab/murmer3.rb
236
241
  - lib/prefab/noop_cache.rb
@@ -238,20 +243,29 @@ files:
238
243
  - lib/prefab/options.rb
239
244
  - lib/prefab/ratelimit_client.rb
240
245
  - lib/prefab/sse_logger.rb
246
+ - lib/prefab/weighted_value_resolver.rb
247
+ - lib/prefab/yaml_config_parser.rb
241
248
  - lib/prefab_pb.rb
242
249
  - lib/prefab_services_pb.rb
243
250
  - prefab-cloud-ruby.gemspec
244
- - run_test_harness_server.sh
245
251
  - test/.prefab.default.config.yaml
246
252
  - test/.prefab.unit_tests.config.yaml
247
- - test/harness_server.rb
253
+ - test/integration_test.rb
254
+ - test/integration_test_helpers.rb
248
255
  - test/test_client.rb
249
256
  - test/test_config_client.rb
250
257
  - test/test_config_loader.rb
251
258
  - test/test_config_resolver.rb
259
+ - test/test_config_value_unwrapper.rb
260
+ - test/test_criteria_evaluator.rb
252
261
  - test/test_feature_flag_client.rb
253
262
  - test/test_helper.rb
263
+ - test/test_integration.rb
264
+ - test/test_local_config_parser.rb
265
+ - test/test_log_path_collector.rb
254
266
  - test/test_logger.rb
267
+ - test/test_options.rb
268
+ - test/test_weighted_value_resolver.rb
255
269
  homepage: http://github.com/prefab-cloud/prefab-cloud-ruby
256
270
  licenses:
257
271
  - MIT
@@ -1,31 +0,0 @@
1
- # frozen_string_literal: true
2
- module Prefab
3
- module ConfigHelper
4
- def value_of(config_value)
5
- case config_value.type
6
- when :string
7
- config_value.string
8
- when :int
9
- config_value.int
10
- when :double
11
- config_value.double
12
- when :bool
13
- config_value.bool
14
- when :feature_flag
15
- config_value.feature_flag
16
- when :segment
17
- config_value.segment
18
- when :log_level
19
- config_value.log_level
20
- end
21
- end
22
-
23
- def value_of_variant(feature_flag_variant)
24
- return feature_flag_variant.string if feature_flag_variant.has_string?
25
- return feature_flag_variant.int if feature_flag_variant.has_int?
26
- return feature_flag_variant.double if feature_flag_variant.has_double?
27
- return feature_flag_variant.bool if feature_flag_variant.has_bool?
28
- return nil
29
- end
30
- end
31
- end
@@ -1,8 +0,0 @@
1
- #! /usr/bin/env bash
2
-
3
- PREFAB_CDN_URL="https://api-prefab-cloud.global.ssl.fastly.net" \
4
- PREFAB_LOG_CLIENT_BOOTSTRAP_LOG_LEVEL=debug \
5
- PREFAB_CLOUD_HTTP=true \
6
- PREFAB_API_KEY="1|local_development_api_key" \
7
- PREFAB_GRPC_URL="localhost:50051" \
8
- ruby -Ilib test/harness_server.rb
@@ -1,64 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'prefab-cloud-ruby'
3
- require 'rack'
4
- require 'base64'
5
- require 'json'
6
-
7
- handler = Rack::Handler::Thin
8
-
9
- #
10
- # This is a very lightweight server that allows the compliance harness to excercise the prefab client
11
- #
12
- class RackApp
13
- def call(env)
14
- props = CGI::parse(env["QUERY_STRING"])
15
- props = JSON.parse(Base64.decode64(props["props"][0]))
16
-
17
- key = props["key"]
18
- namespace = props["namespace"]
19
- api_key = props["api_key"]
20
- user_key = props["user_key"]
21
- is_feature_flag = !props["feature_flag"].nil?
22
- attributes = props["attributes"]
23
- puts props
24
-
25
- options = Prefab::Options.new(
26
- api_key: api_key,
27
- namespace: namespace,
28
- initialization_timeout_sec: 1,
29
- # We want to `return` rather than raise so we'll use the initial payload if we can't connect to the SSE server
30
- on_init_failure: Prefab::Options::ON_INITIALIZATION_FAILURE::RETURN,
31
- # Want to return `nil` rather than raise so we can verify empty values
32
- on_no_default: Prefab::Options::ON_NO_DEFAULT::RETURN_NIL
33
- )
34
-
35
- client = Prefab::Client.new(options)
36
-
37
- puts "Key #{key}"
38
- puts "User #{user_key}"
39
- puts "api_key #{api_key}"
40
- puts "Namespace #{namespace}"
41
- puts "Props! #{props}"
42
- puts "is_feature_flag! #{is_feature_flag}"
43
-
44
- puts client.config_client.to_s
45
-
46
- if is_feature_flag
47
- puts "EVALFF #{key} #{user_key}"
48
- rtn = client.feature_flag_client.get(key, user_key, attributes).to_s
49
- else
50
- rtn = client.config_client.get(key).to_s
51
- end
52
-
53
- puts "return #{rtn}"
54
-
55
- [200, { "Content-Type" => "text/plain" }, rtn]
56
-
57
- rescue Exception => e
58
- puts "ERROR #{e.message}"
59
- puts e.backtrace
60
- [500, { "Content-Type" => "text/plain" }, e.message]
61
- end
62
- end
63
-
64
- handler.run RackApp.new