prefab-cloud-ruby 0.20.0 → 0.22.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -1,176 +1,44 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Prefab
3
4
  class FeatureFlagClient
4
- include Prefab::ConfigHelper
5
- MAX_32_FLOAT = 4294967294.0
6
-
7
5
  def initialize(base_client)
8
6
  @base_client = base_client
9
7
  end
10
8
 
11
- def upsert(feature_name, feature_obj)
12
- @base_client.config_client.upsert(feature_name, Prefab::ConfigValue.new(feature_flag: feature_obj))
13
- end
14
-
15
9
  def feature_is_on?(feature_name)
16
10
  feature_is_on_for?(feature_name, nil)
17
11
  end
18
12
 
19
13
  def feature_is_on_for?(feature_name, lookup_key, attributes: {})
20
- @base_client.stats.increment("prefab.featureflag.on", tags: ["feature:#{feature_name}"])
14
+ @base_client.stats.increment('prefab.featureflag.on', tags: ["feature:#{feature_name}"])
21
15
 
22
- return is_on?(_get(feature_name, lookup_key, attributes, default: false))
23
- end
24
-
25
- def get(feature_name, lookup_key=nil, attributes={}, default: false)
26
- variant = _get(feature_name, lookup_key, attributes, default: default)
16
+ variant = @base_client.config_client.get(feature_name, false, attributes, lookup_key)
27
17
 
28
- value_of_variant_or_nil(variant, default)
18
+ is_on?(variant)
29
19
  end
30
20
 
31
- private
21
+ def get(feature_name, lookup_key = nil, attributes = {}, default: false)
22
+ value = _get(feature_name, lookup_key, attributes)
32
23
 
33
- def value_of_variant_or_nil(variant_maybe, default)
34
- if variant_maybe.nil?
35
- default != Prefab::Client::NO_DEFAULT_PROVIDED ? default : nil
36
- else
37
- value_of_variant(variant_maybe)
38
- end
24
+ value.nil? ? default : value
39
25
  end
40
26
 
41
- def _get(feature_name, lookup_key=nil, attributes={}, default:)
42
- feature_obj = @base_client.config_client.get(feature_name, default)
43
- config_obj = @base_client.config_client.get_config_obj(feature_name)
44
-
45
- return nil if feature_obj.nil? || config_obj.nil?
46
-
47
- if feature_obj == !!feature_obj
48
- return feature_obj
49
- end
27
+ private
50
28
 
51
- variants = config_obj.variants
52
- get_variant(feature_name, lookup_key, attributes, feature_obj, variants)
29
+ def _get(feature_name, lookup_key = nil, attributes = {})
30
+ @base_client.config_client.get(feature_name, nil, attributes, lookup_key)
53
31
  end
54
32
 
55
33
  def is_on?(variant)
56
- if variant.nil?
57
- return false
58
- end
34
+ return false if variant.nil?
59
35
 
60
- if variant == !!variant
61
- return variant
62
- end
36
+ return variant if variant == !!variant
63
37
 
64
38
  variant.bool
65
- rescue
39
+ rescue StandardError
66
40
  @base_client.log.info("is_on? methods only work for boolean feature flags variants. This feature flags variant is '#{variant}'. Returning false")
67
41
  false
68
42
  end
69
-
70
- def get_variant(feature_name, lookup_key, attributes, feature_obj, variants)
71
- if !feature_obj.active
72
- return get_variant_obj(variants, feature_obj.inactive_variant_idx)
73
- end
74
-
75
- #default to inactive
76
- variant_weights = [Prefab::VariantWeight.new(variant_idx: feature_obj.inactive_variant_idx, weight: 1)]
77
-
78
- # if rules.match
79
- feature_obj.rules.each do |rule|
80
- if criteria_match?(rule.criteria, lookup_key, attributes)
81
- variant_weights = rule.variant_weights
82
- break
83
- end
84
- end
85
-
86
- percent_through_distribution = rand()
87
- if lookup_key
88
- percent_through_distribution = get_user_pct(feature_name, lookup_key)
89
- end
90
-
91
- variant_idx = get_variant_idx_from_weights(variant_weights, percent_through_distribution, feature_name)
92
-
93
- return get_variant_obj(variants, variant_idx)
94
- end
95
-
96
- def get_variant_obj(variants, idx)
97
- # our array is 0 based, but the idx are 1 based so the protos are clearly set
98
- return variants[idx - 1] if variants.length >= idx
99
- nil
100
- end
101
-
102
- def get_variant_idx_from_weights(variant_weights, percent_through_distribution, feature_name)
103
- distrubution_space = variant_weights.inject(0) { |sum, v| sum + v.weight }
104
- bucket = distrubution_space * percent_through_distribution
105
- sum = 0
106
- variant_weights.each do |variant_weight|
107
- if bucket < sum + variant_weight.weight
108
- return variant_weight.variant_idx
109
- else
110
- sum += variant_weight.weight
111
- end
112
- end
113
- # variants didn't add up to 100%
114
- @base_client.log.info("Variants of #{feature_name} did not add to 100%")
115
- return variant_weights.last.variant_idx
116
- end
117
-
118
- def get_user_pct(feature, lookup_key)
119
- to_hash = "#{feature}#{lookup_key}"
120
- int_value = Murmur3.murmur3_32(to_hash)
121
- int_value / MAX_32_FLOAT
122
- end
123
-
124
- def criteria_match?(criteria, lookup_key, attributes)
125
- case criteria.operator
126
- when :ALWAYS_TRUE
127
- true
128
- when :LOOKUP_KEY_IN
129
- criteria.values.include?(lookup_key)
130
- when :LOOKUP_KEY_NOT_IN
131
- !criteria.values.include?(lookup_key)
132
- when :IN_SEG
133
- segment_matches?(criteria.values, lookup_key, attributes)
134
- when :NOT_IN_SEG
135
- !segment_matches?(criteria.values, lookup_key, attributes)
136
- when :PROP_IS_ONE_OF
137
- criteria.values.include?(attribute_value(attributes, criteria.property))
138
- when :PROP_IS_NOT_ONE_OF
139
- !criteria.values.include?(attribute_value(attributes, criteria.property))
140
- when :PROP_ENDS_WITH_ONE_OF
141
- criteria.values.any? { |value| attribute_value(attributes, criteria.property)&.end_with?(value) }
142
- when :PROP_DOES_NOT_END_WITH_ONE_OF
143
- criteria.values.none? { |value| attribute_value(attributes, criteria.property)&.end_with?(value) }
144
- else
145
- @base_client.log.info("Unknown Operator: #{criteria.operator}")
146
- false
147
- end
148
- end
149
-
150
- def attribute_value(attributes, property)
151
- attributes[property] || attributes[property.to_sym]
152
- end
153
-
154
- # evaluate each segment key and return whether any match
155
- # there should be an associated segment available as a standard config obj
156
- def segment_matches?(segment_keys, lookup_key, attributes)
157
- segment_keys.any? do |segment_key|
158
- segment = @base_client.config_client.get(segment_key)
159
- if segment.nil?
160
- @base_client.log.info("Missing Segment")
161
- false
162
- else
163
- segment_match?(segment, lookup_key, attributes)
164
- end
165
- end
166
- end
167
-
168
- # does a given segment match?
169
- def segment_match?(segment, lookup_key, attributes)
170
- segment.criterion.any? do |criteria|
171
- criteria_match?(criteria, lookup_key, attributes)
172
- end
173
- end
174
43
  end
175
44
  end
176
-
@@ -1,28 +1,29 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Prefab
3
- class InternalLogger < Logger
4
+ class InternalLogger < ::Logger
4
5
  def initialize(path, logger)
5
6
  @path = path
6
7
  @logger = logger
7
8
  end
8
9
 
9
- def debug(progname = nil, &block)
10
+ def debug(progname = nil)
10
11
  @logger.log_internal yield, @path, progname, DEBUG
11
12
  end
12
13
 
13
- def info(progname = nil, &block)
14
+ def info(progname = nil)
14
15
  @logger.log_internal yield, @path, progname, INFO
15
16
  end
16
17
 
17
- def warn(progname = nil, &block)
18
+ def warn(progname = nil)
18
19
  @logger.log_internal yield, @path, progname, WARN
19
20
  end
20
21
 
21
- def error(progname = nil, &block)
22
+ def error(progname = nil)
22
23
  @logger.log_internal yield, @path, progname, ERROR
23
24
  end
24
25
 
25
- def fatal(progname = nil, &block)
26
+ def fatal(progname = nil)
26
27
  @logger.log_internal yield, @path, progname, FATAL
27
28
  end
28
29
  end
@@ -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
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Prefab
4
+ class LogPathCollector
5
+ INCREMENT = ->(count) { (count || 0) + 1 }
6
+
7
+ SEVERITY_KEY = {
8
+ ::Logger::DEBUG => 'debugs',
9
+ ::Logger::INFO => 'infos',
10
+ ::Logger::WARN => 'warns',
11
+ ::Logger::ERROR => 'errors',
12
+ ::Logger::FATAL => 'fatals'
13
+ }.freeze
14
+
15
+ def initialize(client:, max_paths:, sync_interval:)
16
+ @max_paths = max_paths
17
+ @sync_interval = sync_interval
18
+ @client = client
19
+ @start_at = now
20
+
21
+ @pool = Concurrent::ThreadPoolExecutor.new(
22
+ fallback_policy: :discard,
23
+ max_queue: 5,
24
+ max_threads: 4,
25
+ min_threads: 1,
26
+ name: 'prefab-log-paths'
27
+ )
28
+
29
+ @paths = Concurrent::Map.new
30
+
31
+ start_periodic_sync
32
+ end
33
+
34
+ def push(path, severity)
35
+ return unless @paths.size < @max_paths
36
+
37
+ @paths.compute([path, severity], &INCREMENT)
38
+ end
39
+
40
+ private
41
+
42
+ def sync
43
+ return if @paths.size.zero?
44
+
45
+ log_internal "Syncing #{@paths.size} paths"
46
+
47
+ flush
48
+ end
49
+
50
+ def flush
51
+ to_ship = @paths.dup
52
+ @paths.clear
53
+
54
+ start_at_was = @start_at
55
+ @start_at = now
56
+
57
+ @pool.post do
58
+ log_internal "Uploading stats for #{to_ship.size} paths"
59
+
60
+ aggregate = Hash.new { |h, k| h[k] = Prefab::Logger.new }
61
+
62
+ to_ship.each do |(path, severity), count|
63
+ aggregate[path][SEVERITY_KEY[severity]] = count
64
+ aggregate[path]['logger_name'] = path
65
+ end
66
+
67
+ loggers = Prefab::Loggers.new(
68
+ loggers: aggregate.values,
69
+ start_at: start_at_was,
70
+ end_at: now,
71
+ instance_hash: @client.instance_hash,
72
+ namespace: @client.namespace
73
+ )
74
+
75
+ @client.request Prefab::LoggerReportingService, :send, req_options: {}, params: loggers
76
+ end
77
+ end
78
+
79
+ def start_periodic_sync
80
+ Thread.new do
81
+ log_internal "Initialized log path collector instance_hash=#{@client.instance_hash} max_paths=#{@max_paths} sync_interval=#{@sync_interval}"
82
+
83
+ loop do
84
+ sleep @sync_interval
85
+ sync
86
+ end
87
+ end
88
+ end
89
+
90
+ def log_internal(message)
91
+ @client.log.log_internal message, 'log_path_collector', nil, ::Logger::INFO
92
+ end
93
+
94
+ def now
95
+ (Time.now.utc.to_f * 1000).to_i
96
+ end
97
+ end
98
+ end
@@ -1,52 +1,57 @@
1
1
  # frozen_string_literal: true
2
- module Prefab
3
- class LoggerClient < Logger
4
2
 
5
- SEP = "."
6
- BASE_KEY = "log-level"
7
- UNKNOWN_PATH = "unknown."
8
- INTERNAL_PREFIX = "cloud.prefab.client"
3
+ require 'prefab/log_path_collector'
4
+
5
+ module Prefab
6
+ class LoggerClient < ::Logger
7
+ SEP = '.'
8
+ BASE_KEY = 'log-level'
9
+ UNKNOWN_PATH = 'unknown.'
10
+ INTERNAL_PREFIX = 'cloud.prefab.client'
9
11
 
10
12
  LOG_LEVEL_LOOKUPS = {
11
- Prefab::LogLevel::NOT_SET_LOG_LEVEL => Logger::DEBUG,
12
- Prefab::LogLevel::TRACE => Logger::DEBUG,
13
- Prefab::LogLevel::DEBUG => Logger::DEBUG,
14
- Prefab::LogLevel::INFO => Logger::INFO,
15
- Prefab::LogLevel::WARN => Logger::WARN,
16
- Prefab::LogLevel::ERROR => Logger::ERROR,
17
- Prefab::LogLevel::FATAL => Logger::FATAL
13
+ Prefab::LogLevel::NOT_SET_LOG_LEVEL => ::Logger::DEBUG,
14
+ Prefab::LogLevel::TRACE => ::Logger::DEBUG,
15
+ Prefab::LogLevel::DEBUG => ::Logger::DEBUG,
16
+ Prefab::LogLevel::INFO => ::Logger::INFO,
17
+ Prefab::LogLevel::WARN => ::Logger::WARN,
18
+ Prefab::LogLevel::ERROR => ::Logger::ERROR,
19
+ Prefab::LogLevel::FATAL => ::Logger::FATAL
18
20
  }
19
21
 
20
- def initialize(logdev, formatter: nil, prefix: nil)
22
+ def initialize(logdev, log_path_collector: nil, formatter: nil, prefix: nil)
21
23
  super(logdev)
22
24
  self.formatter = formatter
23
25
  @config_client = BootstrappingConfigClient.new
24
26
  @silences = Concurrent::Map.new(initial_capacity: 2)
25
- @prefix = prefix
27
+ @prefix = "#{prefix}#{prefix && '.'}"
28
+
29
+ @log_path_collector = log_path_collector
26
30
  end
27
31
 
28
32
  def add(severity, message = nil, progname = nil, loc, &block)
29
- path = get_loc_path(loc)
30
- path = "#{@prefix}#{@prefix && '.'}#{path}"
33
+ path_loc = get_loc_path(loc)
34
+ path = @prefix + path_loc
35
+
36
+ @log_path_collector&.push(path_loc, severity)
31
37
 
32
38
  log(message, path, progname, severity, &block)
33
39
  end
34
40
 
35
41
  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
42
+ path = if path
43
+ "#{INTERNAL_PREFIX}.#{path}"
44
+ else
45
+ INTERNAL_PREFIX
46
+ end
41
47
 
42
48
  log(message, path, progname, severity, &block)
43
49
  end
44
50
 
45
- def log(message, path, progname, severity, &block)
46
- severity ||= Logger::UNKNOWN
47
- if @logdev.nil? || severity < level_of(path) || @silences[local_log_id]
48
- return true
49
- end
51
+ def log(message, path, progname, severity)
52
+ severity ||= ::Logger::UNKNOWN
53
+
54
+ return true if @logdev.nil? || severity < level_of(path) || @silences[local_log_id]
50
55
 
51
56
  progname = "#{path}: #{progname || @progname}"
52
57
 
@@ -60,7 +65,8 @@ module Prefab
60
65
  end
61
66
 
62
67
  @logdev.write(
63
- format_message(format_severity(severity), Time.now, progname, message))
68
+ format_message(format_severity(severity), Time.now, progname, message)
69
+ )
64
70
  true
65
71
  end
66
72
 
@@ -85,23 +91,23 @@ module Prefab
85
91
  end
86
92
 
87
93
  def debug?
88
- true;
94
+ true
89
95
  end
90
96
 
91
97
  def info?
92
- true;
98
+ true
93
99
  end
94
100
 
95
101
  def warn?
96
- true;
102
+ true
97
103
  end
98
104
 
99
105
  def error?
100
- true;
106
+ true
101
107
  end
102
108
 
103
109
  def fatal?
104
- true;
110
+ true
105
111
  end
106
112
 
107
113
  def level
@@ -128,13 +134,10 @@ module Prefab
128
134
  # Find the closest match to 'log_level.path' in config
129
135
  def level_of(path)
130
136
  closest_log_level_match = @config_client.get(BASE_KEY, :WARN)
131
- path.split(SEP).inject([BASE_KEY]) do |memo, n|
137
+ path.split(SEP).each_with_object([BASE_KEY]) do |n, memo|
132
138
  memo << n
133
139
  val = @config_client.get(memo.join(SEP), nil)
134
- unless val.nil?
135
- closest_log_level_match = val
136
- end
137
- memo
140
+ closest_log_level_match = val unless val.nil?
138
141
  end
139
142
  closest_log_level_match_int = Prefab::LogLevel.resolve(closest_log_level_match)
140
143
  LOG_LEVEL_LOOKUPS[closest_log_level_match_int]
@@ -150,10 +153,10 @@ module Prefab
150
153
  def get_path(absolute_path, base_label)
151
154
  path = (absolute_path || UNKNOWN_PATH).dup
152
155
  path.slice! Dir.pwd
153
- path.gsub!(/(.*)?(?=\/lib)/im, "") # replace everything before first lib
156
+ path.gsub!(%r{(.*)?(?=/lib)}im, '') # replace everything before first lib
154
157
 
155
- path = path.gsub("/", SEP).gsub(/.rb.*/, "") + SEP + base_label
156
- path.slice! ".lib"
158
+ path = path.gsub('/', SEP).gsub(/.rb.*/, '') + SEP + base_label
159
+ path.slice! '.lib'
157
160
  path.slice! SEP
158
161
  path
159
162
  end
@@ -162,9 +165,8 @@ module Prefab
162
165
  # StubConfigClient to be used while config client initializes
163
166
  # since it may log
164
167
  class BootstrappingConfigClient
165
- def get(key, default = nil)
166
- ENV["PREFAB_LOG_CLIENT_BOOTSTRAP_LOG_LEVEL"] ? ENV["PREFAB_LOG_CLIENT_BOOTSTRAP_LOG_LEVEL"].upcase.to_sym : default
168
+ def get(_key, default = nil)
169
+ ENV['PREFAB_LOG_CLIENT_BOOTSTRAP_LOG_LEVEL'] ? ENV['PREFAB_LOG_CLIENT_BOOTSTRAP_LOG_LEVEL'].upcase.to_sym : default
167
170
  end
168
171
  end
169
172
  end
170
-
@@ -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