prefab-cloud-ruby 0.19.0 → 0.21.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 (53) hide show
  1. checksums.yaml +4 -4
  2. data/.envrc.sample +3 -0
  3. data/.github/workflows/ruby.yml +4 -0
  4. data/.gitmodules +3 -0
  5. data/Gemfile +12 -12
  6. data/Gemfile.lock +16 -14
  7. data/README.md +1 -1
  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 +33 -24
  13. data/lib/prefab/config_client.rb +55 -66
  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 +6 -5
  21. data/lib/prefab/local_config_parser.rb +110 -0
  22. data/lib/prefab/logger_client.rb +30 -36
  23. data/lib/prefab/murmer3.rb +3 -4
  24. data/lib/prefab/noop_cache.rb +5 -7
  25. data/lib/prefab/noop_stats.rb +2 -3
  26. data/lib/prefab/options.rb +11 -9
  27. data/lib/prefab/ratelimit_client.rb +11 -13
  28. data/lib/prefab/sse_logger.rb +3 -2
  29. data/lib/prefab/weighted_value_resolver.rb +42 -0
  30. data/lib/prefab/yaml_config_parser.rb +32 -0
  31. data/lib/prefab-cloud-ruby.rb +7 -2
  32. data/lib/prefab_pb.rb +49 -43
  33. data/lib/prefab_services_pb.rb +0 -1
  34. data/prefab-cloud-ruby.gemspec +28 -19
  35. data/test/.prefab.unit_tests.config.yaml +3 -2
  36. data/test/integration_test.rb +98 -0
  37. data/test/integration_test_helpers.rb +37 -0
  38. data/test/test_client.rb +32 -31
  39. data/test/test_config_client.rb +21 -20
  40. data/test/test_config_loader.rb +48 -37
  41. data/test/test_config_resolver.rb +312 -135
  42. data/test/test_config_value_unwrapper.rb +83 -0
  43. data/test/test_criteria_evaluator.rb +533 -0
  44. data/test/test_feature_flag_client.rb +35 -347
  45. data/test/test_helper.rb +18 -14
  46. data/test/test_integration.rb +33 -0
  47. data/test/test_local_config_parser.rb +78 -0
  48. data/test/test_logger.rb +90 -42
  49. data/test/test_weighted_value_resolver.rb +65 -0
  50. metadata +24 -27
  51. data/lib/prefab/config_helper.rb +0 -31
  52. data/run_test_harness_server.sh +0 -8
  53. data/test/harness_server.rb +0 -64
@@ -0,0 +1,110 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Prefab
4
+ class LocalConfigParser
5
+ class << self
6
+ def parse(key, value, config, file)
7
+ if value.instance_of?(Hash)
8
+ if value['feature_flag']
9
+ config[key] = feature_flag_config(file, key, value)
10
+ else
11
+ value.each do |nest_key, nest_value|
12
+ nested_key = "#{key}.#{nest_key}"
13
+ nested_key = key if nest_key == '_'
14
+ parse(nested_key, nest_value, config, file)
15
+ end
16
+ end
17
+ else
18
+ config[key] = {
19
+ source: file,
20
+ match: 'default',
21
+ config: Prefab::Config.new(
22
+ config_type: :CONFIG,
23
+ key: key,
24
+ rows: [
25
+ Prefab::ConfigRow.new(values: [
26
+ Prefab::ConditionalValue.new(value: value_from(key, value))
27
+ ])
28
+ ]
29
+ )
30
+ }
31
+ end
32
+
33
+ config
34
+ end
35
+
36
+ def value_from(key, raw)
37
+ case raw
38
+ when String
39
+ if key.to_s.start_with? Prefab::LoggerClient::BASE_KEY
40
+ prefab_log_level_resolve = Prefab::LogLevel.resolve(raw.upcase.to_sym) || Prefab::LogLevel::NOT_SET_LOG_LEVEL
41
+ { log_level: prefab_log_level_resolve }
42
+ else
43
+ { string: raw }
44
+ end
45
+ when Integer
46
+ { int: raw }
47
+ when TrueClass, FalseClass
48
+ { bool: raw }
49
+ when Float
50
+ { double: raw }
51
+ end
52
+ end
53
+
54
+ def feature_flag_config(file, key, value)
55
+ criterion = (parse_criterion(value['criterion']) if value['criterion'])
56
+
57
+ variant = Prefab::ConfigValue.new(value_from(key, value['value']))
58
+
59
+ row = Prefab::ConfigRow.new(
60
+ values: [
61
+ Prefab::ConditionalValue.new(
62
+ criteria: [criterion].compact,
63
+ value: Prefab::ConfigValue.new(
64
+ weighted_values: Prefab::WeightedValues.new(weighted_values: [
65
+ Prefab::WeightedValue.new(
66
+ weight: 1000,
67
+ value: variant
68
+ )
69
+ ])
70
+ )
71
+ )
72
+ ]
73
+ )
74
+
75
+ raise Prefab::Error, "Feature flag config `#{key}` #{file} must have a `value`" unless value.key?('value')
76
+
77
+ {
78
+ source: file,
79
+ match: key,
80
+ config: Prefab::Config.new(
81
+ config_type: :FEATURE_FLAG,
82
+ key: key,
83
+ allowable_values: [variant],
84
+ rows: [row]
85
+ )
86
+ }
87
+ end
88
+
89
+ def parse_criterion(criterion)
90
+ Prefab::Criterion.new(operator: criterion['operator'],
91
+ property_name: parse_property(criterion),
92
+ value_to_match: parse_value_to_match(criterion['values']))
93
+ end
94
+
95
+ def parse_property(criterion)
96
+ if criterion['operator'] == 'LOOKUP_KEY_IN'
97
+ Prefab::CriteriaEvaluator::LOOKUP_KEY
98
+ else
99
+ criterion['property']
100
+ end
101
+ end
102
+
103
+ def parse_value_to_match(values)
104
+ raise "Can't handle #{values}" unless values.instance_of?(Array)
105
+
106
+ Prefab::ConfigValue.new(string_list: Prefab::StringList.new(values: values))
107
+ end
108
+ end
109
+ end
110
+ end
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Prefab
3
4
  class LoggerClient < Logger
4
-
5
- SEP = "."
6
- BASE_KEY = "log-level"
7
- UNKNOWN_PATH = "unknown."
8
- INTERNAL_PREFIX = "cloud.prefab.client"
5
+ SEP = '.'
6
+ BASE_KEY = 'log-level'
7
+ UNKNOWN_PATH = 'unknown.'
8
+ INTERNAL_PREFIX = 'cloud.prefab.client'
9
9
 
10
10
  LOG_LEVEL_LOOKUPS = {
11
11
  Prefab::LogLevel::NOT_SET_LOG_LEVEL => Logger::DEBUG,
@@ -33,25 +33,21 @@ module Prefab
33
33
  end
34
34
 
35
35
  def log_internal(message, path = nil, progname, severity, &block)
36
- if path
37
- path = "#{INTERNAL_PREFIX}.#{path}"
38
- else
39
- path = INTERNAL_PREFIX
40
- end
36
+ path = if path
37
+ "#{INTERNAL_PREFIX}.#{path}"
38
+ else
39
+ INTERNAL_PREFIX
40
+ end
41
41
 
42
42
  log(message, path, progname, severity, &block)
43
43
  end
44
44
 
45
- def log(message, path, progname, severity, &block)
46
- level = level_of(path)
47
- progname = "#{path}: #{progname}"
45
+ def log(message, path, progname, severity)
48
46
  severity ||= Logger::UNKNOWN
49
- if @logdev.nil? || severity < level || @silences[local_log_id]
50
- return true
51
- end
52
- if progname.nil?
53
- progname = @progname
54
- end
47
+ return true if @logdev.nil? || severity < level_of(path) || @silences[local_log_id]
48
+
49
+ progname = "#{path}: #{progname || @progname}"
50
+
55
51
  if message.nil?
56
52
  if block_given?
57
53
  message = yield
@@ -60,8 +56,10 @@ module Prefab
60
56
  progname = @progname
61
57
  end
62
58
  end
59
+
63
60
  @logdev.write(
64
- format_message(format_severity(severity), Time.now, progname, message))
61
+ format_message(format_severity(severity), Time.now, progname, message)
62
+ )
65
63
  true
66
64
  end
67
65
 
@@ -86,23 +84,23 @@ module Prefab
86
84
  end
87
85
 
88
86
  def debug?
89
- true;
87
+ true
90
88
  end
91
89
 
92
90
  def info?
93
- true;
91
+ true
94
92
  end
95
93
 
96
94
  def warn?
97
- true;
95
+ true
98
96
  end
99
97
 
100
98
  def error?
101
- true;
99
+ true
102
100
  end
103
101
 
104
102
  def fatal?
105
- true;
103
+ true
106
104
  end
107
105
 
108
106
  def level
@@ -129,13 +127,10 @@ module Prefab
129
127
  # Find the closest match to 'log_level.path' in config
130
128
  def level_of(path)
131
129
  closest_log_level_match = @config_client.get(BASE_KEY, :WARN)
132
- path.split(SEP).inject([BASE_KEY]) do |memo, n|
130
+ path.split(SEP).each_with_object([BASE_KEY]) do |n, memo|
133
131
  memo << n
134
132
  val = @config_client.get(memo.join(SEP), nil)
135
- unless val.nil?
136
- closest_log_level_match = val
137
- end
138
- memo
133
+ closest_log_level_match = val unless val.nil?
139
134
  end
140
135
  closest_log_level_match_int = Prefab::LogLevel.resolve(closest_log_level_match)
141
136
  LOG_LEVEL_LOOKUPS[closest_log_level_match_int]
@@ -151,10 +146,10 @@ module Prefab
151
146
  def get_path(absolute_path, base_label)
152
147
  path = (absolute_path || UNKNOWN_PATH).dup
153
148
  path.slice! Dir.pwd
154
- path.gsub!(/(.*)?(?=\/lib)/im, "") # replace everything before first lib
149
+ path.gsub!(%r{(.*)?(?=/lib)}im, '') # replace everything before first lib
155
150
 
156
- path = path.gsub("/", SEP).gsub(/.rb.*/, "") + SEP + base_label
157
- path.slice! ".lib"
151
+ path = path.gsub('/', SEP).gsub(/.rb.*/, '') + SEP + base_label
152
+ path.slice! '.lib'
158
153
  path.slice! SEP
159
154
  path
160
155
  end
@@ -163,9 +158,8 @@ module Prefab
163
158
  # StubConfigClient to be used while config client initializes
164
159
  # since it may log
165
160
  class BootstrappingConfigClient
166
- def get(key, default = nil)
167
- ENV["PREFAB_LOG_CLIENT_BOOTSTRAP_LOG_LEVEL"] ? ENV["PREFAB_LOG_CLIENT_BOOTSTRAP_LOG_LEVEL"].upcase.to_sym : default
161
+ def get(_key, default = nil)
162
+ ENV['PREFAB_LOG_CLIENT_BOOTSTRAP_LOG_LEVEL'] ? ENV['PREFAB_LOG_CLIENT_BOOTSTRAP_LOG_LEVEL'].upcase.to_sym : default
168
163
  end
169
164
  end
170
165
  end
171
-
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  class Murmur3
3
4
  ## MurmurHash3 was written by Austin Appleby, and is placed in the public
4
5
  ## domain. The author hereby disclaims copyright to this source code.
@@ -9,7 +10,6 @@ class Murmur3
9
10
  ((x << r) | (x >> (32 - r))) & MASK32
10
11
  end
11
12
 
12
-
13
13
  def self.murmur3_32_fmix(h)
14
14
  h &= MASK32
15
15
  h ^= h >> 16
@@ -25,7 +25,7 @@ class Murmur3
25
25
  (k1 * 0x1b873593) & MASK32
26
26
  end
27
27
 
28
- def self.murmur3_32(str, seed=0)
28
+ def self.murmur3_32(str, seed = 0)
29
29
  h1 = seed
30
30
  numbers = str.unpack('V*C*')
31
31
  tailn = str.length % 4
@@ -33,7 +33,7 @@ class Murmur3
33
33
  for k1 in numbers
34
34
  h1 ^= murmur3_32__mmix(k1)
35
35
  h1 = murmur3_32_rotl(h1, 13)
36
- h1 = (h1*5 + 0xe6546b64) & MASK32
36
+ h1 = (h1 * 5 + 0xe6546b64) & MASK32
37
37
  end
38
38
 
39
39
  unless tail.empty?
@@ -47,5 +47,4 @@ class Murmur3
47
47
  h1 ^= str.length
48
48
  murmur3_32_fmix(h1)
49
49
  end
50
-
51
50
  end
@@ -1,17 +1,15 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Prefab
3
4
  class NoopCache
4
- def fetch(name, opts, &method)
5
+ def fetch(_name, _opts)
5
6
  yield
6
7
  end
7
8
 
8
- def write(name, value, opts=nil)
9
- end
9
+ def write(name, value, opts = nil); end
10
10
 
11
- def read(name)
12
- end
11
+ def read(name); end
13
12
 
14
- def delete(name)
15
- end
13
+ def delete(name); end
16
14
  end
17
15
  end
@@ -1,9 +1,8 @@
1
1
  # frozen_string_literal: true
2
- module Prefab
3
2
 
3
+ module Prefab
4
4
  class NoopStats
5
5
  # receives increment("prefab.ratelimit.limitcheck", {:tags=>["policy_group:page_view", "pass:true"]})
6
- def increment(name, opts={})
7
- end
6
+ def increment(name, opts = {}); end
8
7
  end
9
8
  end
@@ -19,17 +19,19 @@ module Prefab
19
19
  attr_reader :prefab_envs
20
20
 
21
21
  DEFAULT_LOG_FORMATTER = proc { |severity, datetime, progname, msg|
22
- "#{severity.ljust(5)} #{datetime}: #{progname} #{msg}\n"
22
+ "#{severity.ljust(5)} #{datetime}:#{' ' if progname}#{progname} #{msg}\n"
23
23
  }
24
24
 
25
25
  module ON_INITIALIZATION_FAILURE
26
26
  RAISE = 1
27
27
  RETURN = 2
28
28
  end
29
+
29
30
  module ON_NO_DEFAULT
30
31
  RAISE = 1
31
32
  RETURN_NIL = 2
32
33
  end
34
+
33
35
  module DATASOURCES
34
36
  ALL = 1
35
37
  LOCAL_ONLY = 2
@@ -40,20 +42,20 @@ module Prefab
40
42
  logdev: $stdout,
41
43
  stats: NoopStats.new, # receives increment("prefab.limitcheck", {:tags=>["policy_group:page_view", "pass:true"]})
42
44
  shared_cache: NoopCache.new, # Something that quacks like Rails.cache ideally memcached
43
- namespace: "",
45
+ namespace: '',
44
46
  log_formatter: DEFAULT_LOG_FORMATTER,
45
47
  log_prefix: nil,
46
- prefab_api_url: ENV["PREFAB_API_URL"] || 'https://api.prefab.cloud',
47
- prefab_grpc_url: ENV["PREFAB_GRPC_URL"] || 'grpc.prefab.cloud:443',
48
+ prefab_api_url: ENV['PREFAB_API_URL'] || 'https://api.prefab.cloud',
49
+ prefab_grpc_url: ENV['PREFAB_GRPC_URL'] || 'grpc.prefab.cloud:443',
48
50
  on_no_default: ON_NO_DEFAULT::RAISE, # options :raise, :warn_and_return_nil,
49
51
  initialization_timeout_sec: 10, # how long to wait before on_init_failure
50
- on_init_failure: ON_INITIALIZATION_FAILURE::RAISE, #options :unlock_and_continue, :lock_and_keep_trying, :raise
52
+ on_init_failure: ON_INITIALIZATION_FAILURE::RAISE, # options :unlock_and_continue, :lock_and_keep_trying, :raise
51
53
  # new_config_callback: nil, #callback method
52
54
  # live_override_url: nil,
53
- prefab_datasources: ENV['PREFAB_DATASOURCES'] == "LOCAL_ONLY" ? DATASOURCES::LOCAL_ONLY : DATASOURCES::ALL,
55
+ prefab_datasources: ENV['PREFAB_DATASOURCES'] == 'LOCAL_ONLY' ? DATASOURCES::LOCAL_ONLY : DATASOURCES::ALL,
54
56
  prefab_config_override_dir: Dir.home,
55
- prefab_config_classpath_dir: ".",
56
- prefab_envs: ENV['PREFAB_ENVS'].nil? ? [] : ENV['PREFAB_ENVS'].split(",")
57
+ prefab_config_classpath_dir: '.',
58
+ prefab_envs: ENV['PREFAB_ENVS'].nil? ? [] : ENV['PREFAB_ENVS'].split(',')
57
59
  )
58
60
  # debugger
59
61
  @api_key = api_key
@@ -80,7 +82,7 @@ module Prefab
80
82
 
81
83
  # https://api.prefab.cloud -> https://api-prefab-cloud.global.ssl.fastly.net
82
84
  def url_for_api_cdn
83
- ENV['PREFAB_CDN_URL'] || "#{@prefab_api_url.gsub(/\./, "-")}.global.ssl.fastly.net"
85
+ ENV['PREFAB_CDN_URL'] || "#{@prefab_api_url.gsub(/\./, '-')}.global.ssl.fastly.net"
84
86
  end
85
87
  end
86
88
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Prefab
3
4
  class RateLimitClient
4
-
5
5
  def initialize(base_client, timeout)
6
6
  @timeout = timeout
7
7
  @base_client = base_client
@@ -9,14 +9,14 @@ module Prefab
9
9
 
10
10
  def pass?(group)
11
11
  result = acquire([group], 1)
12
- return result.passed
12
+ result.passed
13
13
  end
14
14
 
15
15
  def acquire(groups, acquire_amount, allow_partial_response: false, on_error: :log_and_pass)
16
- expiry_cache_key = "prefab.ratelimit.expiry:#{groups.join(".")}"
16
+ expiry_cache_key = "prefab.ratelimit.expiry:#{groups.join('.')}"
17
17
  expiry = @base_client.shared_cache.read(expiry_cache_key)
18
18
  if !expiry.nil? && Integer(expiry) > Time.now.utc.to_f * 1000
19
- @base_client.stats.increment("prefab.ratelimit.limitcheck.expirycache.hit", tags: [])
19
+ @base_client.stats.increment('prefab.ratelimit.limitcheck.expirycache.hit', tags: [])
20
20
  return Prefab::LimitResponse.new(passed: false, amount: 0)
21
21
  end
22
22
 
@@ -27,16 +27,17 @@ module Prefab
27
27
  allow_partial_response: allow_partial_response
28
28
  )
29
29
 
30
- result = @base_client.request Prefab::RateLimitService, :limit_check, req_options: {timeout: @timeout}, params: req
30
+ result = @base_client.request Prefab::RateLimitService, :limit_check, req_options: { timeout: @timeout },
31
+ params: req
31
32
 
32
33
  reset = result.limit_reset_at
33
34
  @base_client.shared_cache.write(expiry_cache_key, reset) unless reset < 1 # protobuf default int to 0
34
35
 
35
- @base_client.stats.increment("prefab.ratelimit.limitcheck", tags: ["policy_group:#{result.policy_group}", "pass:#{result.passed}"])
36
+ @base_client.stats.increment('prefab.ratelimit.limitcheck',
37
+ tags: ["policy_group:#{result.policy_group}", "pass:#{result.passed}"])
36
38
 
37
39
  result
38
-
39
- rescue => e
40
+ rescue StandardError => e
40
41
  handle_error(e, on_error, groups)
41
42
  end
42
43
 
@@ -48,9 +49,7 @@ module Prefab
48
49
  limit: limit,
49
50
  burst: burst
50
51
  )
51
- unless safety_level.nil?
52
- limit_definition.safety_level = safety_level
53
- end
52
+ limit_definition.safety_level = safety_level unless safety_level.nil?
54
53
  config_value = Prefab::ConfigValue.new(limit_definition: limit_definition)
55
54
  config_delta = Prefab::ConfigClient.value_to_delta(key, config_value)
56
55
  upsert_req = Prefab::UpsertRequest.new(config_delta: config_delta)
@@ -61,7 +60,7 @@ module Prefab
61
60
  private
62
61
 
63
62
  def handle_error(e, on_error, groups)
64
- @base_client.stats.increment("prefab.ratelimit.error", tags: ["type:limit"])
63
+ @base_client.stats.increment('prefab.ratelimit.error', tags: ['type:limit'])
65
64
 
66
65
  message = "ratelimit for #{groups} error: #{e.message}"
67
66
  case on_error
@@ -77,4 +76,3 @@ module Prefab
77
76
  end
78
77
  end
79
78
  end
80
-
@@ -1,12 +1,13 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Prefab
3
4
  class SseLogger < InternalLogger
4
5
  def initialize(logger)
5
- super("sse", logger)
6
+ super('sse', logger)
6
7
  end
7
8
 
8
9
  # The SSE::Client warns on a perfectly normal stream disconnect, recast to info
9
- def warn(progname = nil, &block)
10
+ def warn(progname = nil)
10
11
  @logger.log_internal yield, @path, progname, INFO
11
12
  end
12
13
  end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Prefab
4
+ class WeightedValueResolver
5
+ MAX_32_FLOAT = 4_294_967_294.0
6
+
7
+ def initialize(weights, config_key, lookup_key)
8
+ @weights = weights
9
+ @config_key = config_key
10
+ @lookup_key = lookup_key
11
+ end
12
+
13
+ def resolve
14
+ percent = @lookup_key ? user_percent : rand
15
+
16
+ index = variant_index(percent)
17
+
18
+ @weights[index]
19
+ end
20
+
21
+ def user_percent
22
+ to_hash = "#{@config_key}#{@lookup_key}"
23
+ int_value = Murmur3.murmur3_32(to_hash)
24
+ int_value / MAX_32_FLOAT
25
+ end
26
+
27
+ def variant_index(percent_through_distribution)
28
+ distribution_space = @weights.inject(0) { |sum, v| sum + v.weight }
29
+ bucket = distribution_space * percent_through_distribution
30
+
31
+ sum = 0
32
+ @weights.each_with_index do |variant_weight, index|
33
+ return index if bucket < sum + variant_weight.weight
34
+
35
+ sum += variant_weight.weight
36
+ end
37
+
38
+ # In the event that all weights are zero, return the last variant
39
+ @weights.size - 1
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,32 @@
1
+ require 'yaml'
2
+
3
+ module Prefab
4
+ class YAMLConfigParser
5
+ def initialize(file, client)
6
+ @file = file
7
+ @client = client
8
+ end
9
+
10
+ def merge(config)
11
+ yaml = load
12
+
13
+ yaml.each do |k, v|
14
+ config = Prefab::LocalConfigParser.parse(k, v, config, @file)
15
+ end
16
+
17
+ config
18
+ end
19
+
20
+ private
21
+
22
+ def load
23
+ if File.exist?(@file)
24
+ @client.log_internal Logger::INFO, "Load #{@file}"
25
+ YAML.load_file(@file)
26
+ else
27
+ @client.log_internal Logger::INFO, "No file #{@file}"
28
+ {}
29
+ end
30
+ end
31
+ end
32
+ end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
- require "concurrent/atomics"
2
+
3
+ require 'concurrent/atomics'
3
4
  require 'concurrent'
4
5
  require 'faraday'
5
6
  require 'openssl'
@@ -14,8 +15,12 @@ require 'prefab_services_pb'
14
15
  require 'prefab/options'
15
16
  require 'prefab/internal_logger'
16
17
  require 'prefab/sse_logger'
17
- require 'prefab/config_helper'
18
+ require 'prefab/weighted_value_resolver'
19
+ require 'prefab/config_value_unwrapper'
20
+ require 'prefab/criteria_evaluator'
18
21
  require 'prefab/config_loader'
22
+ require 'prefab/local_config_parser'
23
+ require 'prefab/yaml_config_parser'
19
24
  require 'prefab/config_resolver'
20
25
  require 'prefab/client'
21
26
  require 'prefab/ratelimit_client'