prefab-cloud-ruby 0.8.0 → 0.9.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 171f3c104141000ec55b8c331f9f0439d56e991936c69a032f7c78394560ddea
4
- data.tar.gz: bb2fa93f2bc589c7e58bda95f7ab9519d780d80de212b62e1a29b1e187ab55a1
3
+ metadata.gz: 80a03ec9a75bc4c5d827c746354ff1353fe135a5ab6e31e9beaaf1ca1c27c931
4
+ data.tar.gz: d4c9f02e6bbb54d8d4884cc2d94179f39e859aafe3966188b1a00f7b7e5ccc48
5
5
  SHA512:
6
- metadata.gz: c883ea3ba1f608c5fd88e0371302dca440968ad34fae8c279b735f180a73986498c9a87b95d2d51571daa2be723944568824bf8444425a8ff463c210bb9c7429
7
- data.tar.gz: 278cccca1c2e834e79971394310fdba30c03e806b31708094d90d62ed1623c7c5d2e19cdd204165437a75a8711c979f915f0b1ecd86220991fa22697ddad3a49
6
+ metadata.gz: 67f8b5ed6f61f01943736f9abbb685c9d7f7fd4c029ff3e051356f6e65936595f18899160fd842c415d86c371b0f9d915d795c6b9adafbdebeadd5b6fc6cc75b
7
+ data.tar.gz: c56dd76208ad8bbfd9d7add1bbc317a951671c2590cecf93389fbb5170aa9da13898bb3501e396450df2eaa93a67d7041b24fbdc2ca77f2a414056d0cbf471f9
data/Gemfile CHANGED
@@ -2,6 +2,7 @@ source "https://rubygems.org"
2
2
 
3
3
  gem 'concurrent-ruby', '~> 1.0', '>= 1.0.5'
4
4
  gem 'faraday'
5
+ gem 'ld-eventsource'
5
6
  gem 'grpc', :platforms => :ruby
6
7
  gem 'google-protobuf', :platforms => :ruby
7
8
  gem 'googleapis-common-protos-types', :platforms => :ruby
data/Gemfile.lock CHANGED
@@ -14,12 +14,18 @@ GEM
14
14
  descendants_tracker (0.0.4)
15
15
  thread_safe (~> 0.3, >= 0.3.1)
16
16
  docile (1.3.5)
17
+ domain_name (0.5.20190701)
18
+ unf (>= 0.0.5, < 1.0.0)
17
19
  eventmachine (1.2.7)
18
20
  faraday (1.3.0)
19
21
  faraday-net_http (~> 1.0)
20
22
  multipart-post (>= 1.2, < 3)
21
23
  ruby2_keywords
22
24
  faraday-net_http (1.0.1)
25
+ ffi (1.15.5)
26
+ ffi-compiler (1.0.1)
27
+ ffi (>= 1.0.0)
28
+ rake
23
29
  git (1.8.1)
24
30
  rchardet (~> 1.8)
25
31
  github_api (0.19.0)
@@ -37,6 +43,14 @@ GEM
37
43
  grpc-tools (1.43.1)
38
44
  hashie (3.6.0)
39
45
  highline (2.0.3)
46
+ http (5.0.1)
47
+ addressable (~> 2.3)
48
+ http-cookie (~> 1.0)
49
+ http-form_data (~> 2.2)
50
+ llhttp-ffi (~> 0.3.0)
51
+ http-cookie (1.0.4)
52
+ domain_name (~> 0.5)
53
+ http-form_data (2.3.0)
40
54
  i18n (1.8.9)
41
55
  concurrent-ruby (~> 1.0)
42
56
  json (1.8.6)
@@ -55,6 +69,12 @@ GEM
55
69
  jwt (2.2.2)
56
70
  kamelcase (0.0.2)
57
71
  semver2 (~> 3)
72
+ ld-eventsource (2.2.0)
73
+ concurrent-ruby (~> 1.0)
74
+ http (>= 4.4.1, < 6.0.0)
75
+ llhttp-ffi (0.3.1)
76
+ ffi-compiler (~> 1.0)
77
+ rake (~> 13.0)
58
78
  mini_portile2 (2.7.1)
59
79
  minitest (5.14.4)
60
80
  multi_json (1.15.0)
@@ -96,6 +116,9 @@ GEM
96
116
  thread_safe (0.3.6)
97
117
  tzinfo (1.2.9)
98
118
  thread_safe (~> 0.1)
119
+ unf (0.1.4)
120
+ unf_ext
121
+ unf_ext (0.0.8)
99
122
 
100
123
  PLATFORMS
101
124
  ruby
@@ -109,6 +132,7 @@ DEPENDENCIES
109
132
  grpc
110
133
  grpc-tools
111
134
  juwelier (~> 2.4.9)
135
+ ld-eventsource
112
136
  rdoc (~> 3.12)
113
137
  shoulda
114
138
  simplecov
data/README.md CHANGED
@@ -56,6 +56,9 @@ end
56
56
  ## Release
57
57
 
58
58
  ```shell
59
+ update VERSION
60
+ bundle exec rake gemspec:generate
61
+ git commit & push
59
62
  REMOTE_BRANCH=main LOCAL_BRANCH=main bundle exec rake release
60
63
  ```
61
64
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.8.0
1
+ 0.9.0
data/lib/prefab/client.rb CHANGED
@@ -8,7 +8,7 @@ module Prefab
8
8
  }
9
9
 
10
10
 
11
- attr_reader :project_id, :shared_cache, :stats, :namespace, :interceptor, :api_key, :environment
11
+ attr_reader :project_id, :shared_cache, :stats, :namespace, :interceptor, :api_key, :environment, :prefab_api_url
12
12
 
13
13
  def initialize(api_key: ENV['PREFAB_API_KEY'],
14
14
  logdev: nil,
@@ -31,17 +31,19 @@ module Prefab
31
31
  @namespace = namespace
32
32
  @interceptor = Prefab::AuthInterceptor.new(api_key)
33
33
  @stubs = {}
34
-
34
+ @prefab_api_url = ENV["PREFAB_API_URL"] || 'https://api.prefab.cloud'
35
+ @prefab_grpc_url = ENV["PREFAB_GRPC_URL"] || 'grpc.prefab.cloud:443'
36
+ log_internal Logger::INFO, "Prefab Initializing in environment: '#{@environment}' and namespace: '#{@namespace}'"
37
+ log_internal Logger::INFO, "Prefab Connecting to: #{@prefab_api_url} and #{@prefab_grpc_url} Secure: #{http_secure?}"
35
38
  at_exit do
36
39
  channel.destroy
37
40
  end
38
41
  end
39
42
 
40
43
  def channel
41
- credentials = ENV["PREFAB_CLOUD_HTTP"] == "true" ? :this_channel_is_insecure : creds
42
- url = ENV["PREFAB_API_URL"] || 'grpc.prefab.cloud:443'
43
- log_internal Logger::DEBUG, "GRPC Channel #{url} #{credentials}"
44
- @_channel ||= GRPC::Core::Channel.new(url, nil, credentials)
44
+ credentials = http_secure? ? creds : :this_channel_is_insecure
45
+ log_internal Logger::DEBUG, "GRPC Channel #{@prefab_grpc_url} #{credentials}"
46
+ @_channel ||= GRPC::Core::Channel.new(@prefab_grpc_url, nil, credentials)
45
47
  end
46
48
 
47
49
  def config_client(timeout: 5.0)
@@ -101,6 +103,10 @@ module Prefab
101
103
 
102
104
  private
103
105
 
106
+ def http_secure?
107
+ ENV["PREFAB_CLOUD_HTTP"] != "true"
108
+ end
109
+
104
110
  def stub_for(service, timeout)
105
111
  @stubs["#{service}_#{timeout}"] ||= service::Stub.new(nil,
106
112
  nil,
@@ -29,7 +29,8 @@ module Prefab
29
29
 
30
30
  def start_streaming
31
31
  @streaming = true
32
- start_api_connection_thread(@config_loader.highwater_mark)
32
+ # start_grpc_streaming_connection_thread(@config_loader.highwater_mark)
33
+ start_sse_streaming_connection_thread(@config_loader.highwater_mark)
33
34
  end
34
35
 
35
36
  def get(key)
@@ -62,8 +63,14 @@ module Prefab
62
63
  end
63
64
 
64
65
  def self.value_to_delta(key, config_value, namespace = nil)
65
- Prefab::ConfigDelta.new(key: [namespace, key].compact.join(":"),
66
- value: config_value)
66
+ Prefab::Config.new(key: [namespace, key].compact.join(":"),
67
+ rows: [Prefab::ConfigRow.new(value: config_value)])
68
+ end
69
+
70
+ def get_config_obj(key)
71
+ @initialization_lock.with_read_lock do
72
+ @config_resolver.get_config(key)
73
+ end
67
74
  end
68
75
 
69
76
  private
@@ -92,12 +99,12 @@ module Prefab
92
99
  def load_checkpoint_from_config
93
100
  @base_client.log_internal Logger::DEBUG, "Load Checkpoint From Config"
94
101
 
95
- config_req = Prefab::ConfigServicePointer.new(project_id: @base_client.project_id,
96
- start_at_id: @config_loader.highwater_mark)
102
+ config_req = Prefab::ConfigServicePointer.new(start_at_id: @config_loader.highwater_mark)
103
+
97
104
  resp = stub.get_all_config(config_req)
98
105
  @base_client.log_internal Logger::DEBUG, "Got Response #{resp}"
99
- load_deltas(resp, :api)
100
- resp.deltas.each do |delta|
106
+ load_configs(resp, :api)
107
+ resp.configs.each do |delta|
101
108
  @config_loader.set(delta)
102
109
  end
103
110
  @config_resolver.update
@@ -112,16 +119,16 @@ module Prefab
112
119
  url = "#{@s3_cloud_front}/#{@base_client.api_key.gsub("|", "/")}"
113
120
  resp = Faraday.get url
114
121
  if resp.status == 200
115
- deltas = Prefab::ConfigDeltas.decode(resp.body)
116
- load_deltas(deltas, :s3)
122
+ configs = Prefab::Configs.decode(resp.body)
123
+ load_configs(configs, :s3)
117
124
  else
118
125
  @base_client.log_internal Logger::INFO, "No S3 checkpoint. Response #{resp.status} Plan may not support this."
119
126
  end
120
127
  end
121
128
 
122
- def load_deltas(deltas, source)
123
- deltas.deltas.each do |delta|
124
- @config_loader.set(delta)
129
+ def load_configs(configs, source)
130
+ configs.configs.each do |config|
131
+ @config_loader.set(config)
125
132
  end
126
133
  @base_client.log_internal Logger::INFO, "Found checkpoint with highwater id #{@config_loader.highwater_mark} from #{source}"
127
134
  @base_client.stats.increment("prefab.config.checkpoint.load")
@@ -156,11 +163,35 @@ module Prefab
156
163
  end
157
164
  end
158
165
 
166
+
167
+ def start_sse_streaming_connection_thread(start_at_id)
168
+ auth = "#{@base_client.project_id}:#{@base_client.api_key}"
169
+
170
+ auth_string = Base64.strict_encode64(auth)
171
+ headers = {
172
+ "x-prefab-start-at-id": start_at_id,
173
+ "Authorization": "Basic #{auth_string}",
174
+ }
175
+ url = "#{@base_client.prefab_api_url}/api/v1/sse/config"
176
+ @base_client.log_internal Logger::INFO, "SSE Streaming Connect to #{url}"
177
+ SSE::Client.new(url, headers: headers) do |client|
178
+ client.on_event do |event|
179
+ configs = Prefab::Configs.decode(Base64.decode64(event.data))
180
+ @base_client.log_internal Logger::INFO, "SSE received configs."
181
+ @base_client.log_internal Logger::DEBUG, "SSE received configs: #{configs}"
182
+ configs.configs.each do |config|
183
+ @config_loader.set(config)
184
+ end
185
+ @config_resolver.update
186
+ finish_init!(:streaming)
187
+ end
188
+ end
189
+ end
190
+
159
191
  # Setup a streaming connection to the API
160
192
  # Save new config values into the loader
161
- def start_api_connection_thread(start_at_id)
162
- config_req = Prefab::ConfigServicePointer.new(project_id: @base_client.project_id,
163
- start_at_id: start_at_id)
193
+ def start_grpc_streaming_connection_thread(start_at_id)
194
+ config_req = Prefab::ConfigServicePointer.new(start_at_id: start_at_id)
164
195
  @base_client.log_internal Logger::DEBUG, "start api connection thread #{start_at_id}"
165
196
  @base_client.stats.increment("prefab.config.api.start")
166
197
 
@@ -174,8 +205,8 @@ module Prefab
174
205
  begin
175
206
  resp = stub.get_config(config_req)
176
207
  resp.each do |r|
177
- r.deltas.each do |delta|
178
- @config_loader.set(delta)
208
+ r.configs.each do |config|
209
+ @config_loader.set(config)
179
210
  end
180
211
  @config_resolver.update
181
212
  finish_init!(:streaming)
@@ -20,18 +20,18 @@ module Prefab
20
20
  rtn
21
21
  end
22
22
 
23
- def set(delta)
23
+ def set(config)
24
24
  # don't overwrite newer values
25
- if @api_config[delta.key] && @api_config[delta.key].id > delta.id
25
+ if @api_config[config.key] && @api_config[config.key].id > config.id
26
26
  return
27
27
  end
28
28
 
29
- if delta.default.nil?
30
- @api_config.delete(delta.key)
29
+ if config.rows.empty?
30
+ @api_config.delete(config.key)
31
31
  else
32
- @api_config[delta.key] = delta
32
+ @api_config[config.key] = config
33
33
  end
34
- @highwater_mark = [delta.id, @highwater_mark].max
34
+ @highwater_mark = [config.id, @highwater_mark].max
35
35
  end
36
36
 
37
37
  def rm(key)
@@ -39,11 +39,11 @@ module Prefab
39
39
  end
40
40
 
41
41
  def get_api_deltas
42
- deltas = Prefab::ConfigDeltas.new
42
+ configs = Prefab::Configs.new
43
43
  @api_config.each_value do |config_value|
44
- deltas.deltas << config_value
44
+ configs.configs << config_value
45
45
  end
46
- deltas
46
+ configs
47
47
  end
48
48
 
49
49
  private
@@ -63,7 +63,9 @@ module Prefab
63
63
  Dir.glob(glob).each do |file|
64
64
  yaml = load(file)
65
65
  yaml.each do |k, v|
66
- rtn[k] = Prefab::ConfigDelta.new(key: k, default: Prefab::ConfigValue.new(value_from(v)))
66
+ rtn[k] = Prefab::Config.new(key: k, rows: [
67
+ Prefab::ConfigRow.new(value: Prefab::ConfigValue.new(value_from(v)))
68
+ ])
67
69
  end
68
70
  end
69
71
  rtn
@@ -24,12 +24,15 @@ module Prefab
24
24
  end
25
25
 
26
26
  def get(property)
27
- config = @lock.with_read_lock do
28
- @local_store[property]
29
- end
27
+ config = _get(property)
30
28
  config ? value_of(config[:value]) : nil
31
29
  end
32
30
 
31
+ def get_config(property)
32
+ config = _get(property)
33
+ config ? config[:config] : nil
34
+ end
35
+
33
36
  def update
34
37
  make_local
35
38
  end
@@ -55,46 +58,35 @@ module Prefab
55
58
 
56
59
  def make_local
57
60
  store = {}
58
- @config_loader.calc_config.each do |key, delta|
59
- # start with the top level default
60
- to_store = { match: "default", value: delta.default }
61
- if delta.envs.any?
62
- env_values = delta.envs.select { |e| e.environment == @environment }
63
-
64
- # do we have and env_values that match our env?
65
- if env_values.any?
66
- env_value = env_values.first
67
-
68
- # override the top level default with env default
69
- to_store = { match: "env_default", env: env_value.environment, value: env_value.default }
70
-
71
- if env_value.namespace_values.any?
72
- # check all namespace_values for match
73
- env_value.namespace_values.each do |namespace_value|
74
- (starts_with, count) = starts_with_ns?(namespace_value.namespace, @namespace)
75
- if starts_with
76
- # is this match the best match?
77
- if count > (to_store[:match_depth_count] || 0)
78
- to_store = { match: namespace_value.namespace, count: count, value: namespace_value.config_value }
79
- end
80
- end
61
+ @config_loader.calc_config.each do |key, config|
62
+ sortable = config.rows.map do |row|
63
+ if !row.env_key.empty?
64
+ if row.env_key == @environment
65
+ if !row.namespace.empty?
66
+ (starts_with, count) = starts_with_ns?(row.namespace, @namespace)
67
+ # rubocop:disable BlockNesting
68
+ { sortable: 2 + count, match: row.namespace, value: row.value, config: config} if starts_with
69
+ else
70
+ { sortable: 1, match: row.env_key, value: row.value, config: config}
81
71
  end
82
72
  end
73
+ else
74
+ { sortable: 0, match: "default", value: row.value, config: config}
83
75
  end
84
- end
85
-
86
- # feature flags are a funny case
87
- # we only define the variants in the default in order to be DRY
88
- # but we want to access them in environments, clone them over
89
- if to_store[:value].type == :feature_flag
90
- to_store[:value].feature_flag.variants = delta.default.feature_flag.variants
91
- end
92
-
76
+ end.compact
77
+ to_store = sortable.sort_by { |h| h[:sortable] }.last
93
78
  store[key] = to_store
94
79
  end
80
+
95
81
  @lock.with_write_lock do
96
82
  @local_store = store
97
83
  end
98
84
  end
85
+
86
+ def _get(property)
87
+ @lock.with_read_lock do
88
+ @local_store[property]
89
+ end
90
+ end
99
91
  end
100
92
  end
@@ -24,11 +24,12 @@ module Prefab
24
24
 
25
25
  def get(feature_name, lookup_key, attributes)
26
26
  feature_obj = @base_client.config_client.get(feature_name)
27
- evaluate(feature_name, lookup_key, attributes, feature_obj)
27
+ variants = @base_client.config_client.get_config_obj(feature_name).variants
28
+ evaluate(feature_name, lookup_key, attributes, feature_obj, variants)
28
29
  end
29
30
 
30
- def evaluate(feature_name, lookup_key, attributes, feature_obj)
31
- value_of(get_variant(feature_name, lookup_key, attributes, feature_obj))
31
+ def evaluate(feature_name, lookup_key, attributes, feature_obj, variants)
32
+ value_of(get_variant(feature_name, lookup_key, attributes, feature_obj, variants))
32
33
  end
33
34
 
34
35
  private
@@ -40,9 +41,9 @@ module Prefab
40
41
  variant.bool
41
42
  end
42
43
 
43
- def get_variant(feature_name, lookup_key, attributes, feature_obj)
44
+ def get_variant(feature_name, lookup_key, attributes, feature_obj, variants)
44
45
  if !feature_obj.active
45
- return get_variant_obj(feature_obj, feature_obj.inactive_variant_idx)
46
+ return get_variant_obj(variants, feature_obj.inactive_variant_idx)
46
47
  end
47
48
 
48
49
  variant_distribution = feature_obj.default
@@ -50,7 +51,7 @@ module Prefab
50
51
  # if user_targets.match
51
52
  feature_obj.user_targets.each do |target|
52
53
  if (target.identifiers.include? lookup_key)
53
- return get_variant_obj(feature_obj, target.variant_idx)
54
+ return get_variant_obj(variants, target.variant_idx)
54
55
  end
55
56
  end
56
57
 
@@ -73,11 +74,11 @@ module Prefab
73
74
  variant_idx = get_variant_idx_from_weights(variant_distribution.variant_weights.weights, distribution_bucket, feature_name)
74
75
  end
75
76
 
76
- return get_variant_obj(feature_obj, variant_idx)
77
+ return get_variant_obj(variants, variant_idx)
77
78
  end
78
79
 
79
- def get_variant_obj(feature_obj, idx)
80
- return feature_obj.variants[idx] if feature_obj.variants.length >= idx
80
+ def get_variant_obj(variants, idx)
81
+ return variants[idx] if variants.length >= idx
81
82
  nil
82
83
  end
83
84
 
@@ -2,6 +2,8 @@ require "concurrent/atomics"
2
2
  require 'concurrent'
3
3
  require 'faraday'
4
4
  require 'openssl'
5
+ require 'openssl'
6
+ require 'ld-eventsource'
5
7
  require 'prefab_pb'
6
8
  require 'prefab_services_pb'
7
9
  require 'prefab/config_helper'
data/lib/prefab_pb.rb CHANGED
@@ -22,28 +22,21 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
22
22
  optional :segment, :message, 8, "prefab.Segment"
23
23
  end
24
24
  end
25
- add_message "prefab.NamespaceValue" do
26
- optional :namespace, :string, 1
27
- optional :config_value, :message, 2, "prefab.ConfigValue"
25
+ add_message "prefab.Configs" do
26
+ repeated :configs, :message, 1, "prefab.Config"
28
27
  end
29
- add_message "prefab.EnvironmentValues" do
30
- optional :environment, :string, 1
31
- repeated :namespace_values, :message, 2, "prefab.NamespaceValue"
32
- optional :default, :message, 3, "prefab.ConfigValue"
33
- end
34
- add_message "prefab.ConfigDelta" do
28
+ add_message "prefab.Config" do
35
29
  optional :id, :int64, 1
36
- optional :key, :string, 2
37
- optional :default, :message, 3, "prefab.ConfigValue"
38
- repeated :envs, :message, 4, "prefab.EnvironmentValues"
39
- end
40
- add_message "prefab.ConfigDeltas" do
41
- repeated :deltas, :message, 1, "prefab.ConfigDelta"
42
- end
43
- add_message "prefab.UpsertRequest" do
44
- optional :project_id, :int64, 1
45
- optional :config_delta, :message, 2, "prefab.ConfigDelta"
30
+ optional :project_id, :int64, 2
31
+ optional :key, :string, 3
46
32
  optional :changed_by, :string, 4
33
+ repeated :rows, :message, 5, "prefab.ConfigRow"
34
+ repeated :variants, :message, 6, "prefab.FeatureFlagVariant"
35
+ end
36
+ add_message "prefab.ConfigRow" do
37
+ optional :env_key, :string, 1
38
+ optional :namespace, :string, 2
39
+ optional :value, :message, 3, "prefab.ConfigValue"
47
40
  end
48
41
  add_message "prefab.LimitResponse" do
49
42
  optional :passed, :bool, 1
@@ -137,7 +130,6 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
137
130
  optional :default, :message, 3, "prefab.VariantDistribution"
138
131
  repeated :user_targets, :message, 4, "prefab.UserTarget"
139
132
  repeated :rules, :message, 5, "prefab.Rule"
140
- repeated :variants, :message, 6, "prefab.FeatureFlagVariant"
141
133
  end
142
134
  add_message "prefab.LimitDefinition" do
143
135
  optional :policy_name, :enum, 2, "prefab.LimitResponse.LimitPolicyNames"
@@ -177,6 +169,10 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
177
169
  add_message "prefab.BasicResponse" do
178
170
  optional :message, :string, 1
179
171
  end
172
+ add_message "prefab.CreationResponse" do
173
+ optional :message, :string, 1
174
+ optional :new_id, :int64, 2
175
+ end
180
176
  add_enum "prefab.OnFailure" do
181
177
  value :NOT_SET, 0
182
178
  value :LOG_AND_PASS, 1
@@ -189,11 +185,9 @@ end
189
185
  module Prefab
190
186
  ConfigServicePointer = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ConfigServicePointer").msgclass
191
187
  ConfigValue = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ConfigValue").msgclass
192
- NamespaceValue = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.NamespaceValue").msgclass
193
- EnvironmentValues = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.EnvironmentValues").msgclass
194
- ConfigDelta = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ConfigDelta").msgclass
195
- ConfigDeltas = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ConfigDeltas").msgclass
196
- UpsertRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.UpsertRequest").msgclass
188
+ Configs = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.Configs").msgclass
189
+ Config = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.Config").msgclass
190
+ ConfigRow = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.ConfigRow").msgclass
197
191
  LimitResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.LimitResponse").msgclass
198
192
  LimitResponse::LimitPolicyNames = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.LimitResponse.LimitPolicyNames").enummodule
199
193
  LimitRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.LimitRequest").msgclass
@@ -214,5 +208,6 @@ module Prefab
214
208
  BufferedRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.BufferedRequest").msgclass
215
209
  BatchRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.BatchRequest").msgclass
216
210
  BasicResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.BasicResponse").msgclass
211
+ CreationResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.CreationResponse").msgclass
217
212
  OnFailure = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("prefab.OnFailure").enummodule
218
213
  end
@@ -28,9 +28,9 @@ module Prefab
28
28
  self.unmarshal_class_method = :decode
29
29
  self.service_name = 'prefab.ConfigService'
30
30
 
31
- rpc :GetConfig, ::Prefab::ConfigServicePointer, stream(::Prefab::ConfigDeltas)
32
- rpc :GetAllConfig, ::Prefab::ConfigServicePointer, ::Prefab::ConfigDeltas
33
- rpc :Upsert, ::Prefab::UpsertRequest, ::Prefab::ConfigServicePointer
31
+ rpc :GetConfig, ::Prefab::ConfigServicePointer, stream(::Prefab::Configs)
32
+ rpc :GetAllConfig, ::Prefab::ConfigServicePointer, ::Prefab::Configs
33
+ rpc :Upsert, ::Prefab::Config, ::Prefab::CreationResponse
34
34
  end
35
35
 
36
36
  Stub = Service.rpc_stub_class
@@ -2,16 +2,16 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Juwelier::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: prefab-cloud-ruby 0.8.0 ruby lib
5
+ # stub: prefab-cloud-ruby 0.9.0 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "prefab-cloud-ruby".freeze
9
- s.version = "0.8.0"
9
+ s.version = "0.9.0"
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
12
12
  s.require_paths = ["lib".freeze]
13
13
  s.authors = ["Jeff Dwyer".freeze]
14
- s.date = "2022-02-24"
14
+ s.date = "2022-03-18"
15
15
  s.description = "RateLimits & Config as a service".freeze
16
16
  s.email = "jdwyer@prefab.cloud".freeze
17
17
  s.extra_rdoc_files = [
@@ -67,6 +67,7 @@ Gem::Specification.new do |s|
67
67
  if s.respond_to? :add_runtime_dependency then
68
68
  s.add_runtime_dependency(%q<concurrent-ruby>.freeze, ["~> 1.0", ">= 1.0.5"])
69
69
  s.add_runtime_dependency(%q<faraday>.freeze, [">= 0"])
70
+ s.add_runtime_dependency(%q<ld-eventsource>.freeze, [">= 0"])
70
71
  s.add_runtime_dependency(%q<grpc>.freeze, [">= 0"])
71
72
  s.add_runtime_dependency(%q<google-protobuf>.freeze, [">= 0"])
72
73
  s.add_runtime_dependency(%q<googleapis-common-protos-types>.freeze, [">= 0"])
@@ -80,6 +81,7 @@ Gem::Specification.new do |s|
80
81
  else
81
82
  s.add_dependency(%q<concurrent-ruby>.freeze, ["~> 1.0", ">= 1.0.5"])
82
83
  s.add_dependency(%q<faraday>.freeze, [">= 0"])
84
+ s.add_dependency(%q<ld-eventsource>.freeze, [">= 0"])
83
85
  s.add_dependency(%q<grpc>.freeze, [">= 0"])
84
86
  s.add_dependency(%q<google-protobuf>.freeze, [">= 0"])
85
87
  s.add_dependency(%q<googleapis-common-protos-types>.freeze, [">= 0"])
@@ -1,2 +1,2 @@
1
- PREFAB_LOG_CLIENT_BOOTSTRAP_LOG_LEVEL=debug PREFAB_CLOUD_HTTP=true PREFAB_API_KEY="1|local_development_api_key" PREFAB_API_URL="localhost:50051" ruby -Ilib test/harness_server.rb
1
+ PREFAB_LOG_CLIENT_BOOTSTRAP_LOG_LEVEL=debug PREFAB_CLOUD_HTTP=true PREFAB_GRPC_URL="localhost:50051" ruby -Ilib test/harness_server.rb
2
2
  #GRPC_TRACE=all GRPC_VERBOSITY=DEBUG PREFAB_LOG_CLIENT_BOOTSTRAP_LOG_LEVEL=debug PREFAB_CLOUD_HTTP=true PREFAB_API_KEY="1|local_development_api_key" PREFAB_API_URL="localhost:50051" ruby -Ilib test/harness_server.rb
@@ -20,7 +20,7 @@ class RackApp
20
20
  is_feature_flag = !props["feature_flag"].nil?
21
21
 
22
22
  client = Prefab::Client.new(
23
- api_key: "1-#{environment}-local_development_api_key", #sets environment
23
+ api_key: "1-#{environment}-local_development_api_key-SDK", #sets environment
24
24
  namespace: namespace,
25
25
  )
26
26
 
@@ -40,6 +40,11 @@ class RackApp
40
40
  puts "return #{rtn}"
41
41
 
42
42
  [200, { "Content-Type" => "text/plain" }, rtn]
43
+
44
+ rescue Exception => e
45
+ puts "ERROR #{e.message}"
46
+ puts e.backtrace
47
+ [500, { "Content-Type" => "text/plain" }, e.message]
43
48
  end
44
49
  end
45
50
 
@@ -16,26 +16,26 @@ class TestConfigLoader < Minitest::Test
16
16
 
17
17
  def test_highwater
18
18
  assert_equal 0, @loader.highwater_mark
19
- @loader.set(Prefab::ConfigDelta.new(id: 1, key: "sample_int", default: Prefab::ConfigValue.new(int: 456)))
19
+ @loader.set(Prefab::Config.new(id: 1, key: "sample_int", rows: [Prefab::ConfigRow.new(value: Prefab::ConfigValue.new(int: 456))]))
20
20
  assert_equal 1, @loader.highwater_mark
21
21
 
22
- @loader.set(Prefab::ConfigDelta.new(id: 5, key: "sample_int", default: Prefab::ConfigValue.new(int: 456)))
22
+ @loader.set(Prefab::Config.new(id: 5, key: "sample_int", rows: [Prefab::ConfigRow.new(value: Prefab::ConfigValue.new(int: 456))]))
23
23
  assert_equal 5, @loader.highwater_mark
24
- @loader.set(Prefab::ConfigDelta.new(id: 2, key: "sample_int", default: Prefab::ConfigValue.new(int: 456)))
24
+ @loader.set(Prefab::Config.new(id: 2, key: "sample_int", rows: [Prefab::ConfigRow.new(value: Prefab::ConfigValue.new(int: 456))]))
25
25
  assert_equal 5, @loader.highwater_mark
26
26
  end
27
27
 
28
28
  def test_keeps_most_recent
29
29
  assert_equal 0, @loader.highwater_mark
30
- @loader.set(Prefab::ConfigDelta.new(id: 1, key: "sample_int", default: Prefab::ConfigValue.new(int: 1)))
30
+ @loader.set(Prefab::Config.new(id: 1, key: "sample_int", rows: [Prefab::ConfigRow.new(value: Prefab::ConfigValue.new(int: 1))]))
31
31
  assert_equal 1, @loader.highwater_mark
32
32
  should_be :int, 1, "sample_int"
33
33
 
34
- @loader.set(Prefab::ConfigDelta.new(id: 4, key: "sample_int", default: Prefab::ConfigValue.new(int: 4)))
34
+ @loader.set(Prefab::Config.new(id: 4, key: "sample_int", rows: [Prefab::ConfigRow.new(value: Prefab::ConfigValue.new(int: 4))]))
35
35
  assert_equal 4, @loader.highwater_mark
36
36
  should_be :int, 4, "sample_int"
37
37
 
38
- @loader.set(Prefab::ConfigDelta.new(id: 2, key: "sample_int", default: Prefab::ConfigValue.new(int: 2)))
38
+ @loader.set(Prefab::Config.new(id: 2, key: "sample_int", rows: [Prefab::ConfigRow.new(value: Prefab::ConfigValue.new(int: 2))]))
39
39
  assert_equal 4, @loader.highwater_mark
40
40
  should_be :int, 4, "sample_int"
41
41
  end
@@ -43,37 +43,37 @@ class TestConfigLoader < Minitest::Test
43
43
  def test_api_precedence
44
44
  should_be :int, 123, "sample_int"
45
45
 
46
- @loader.set(Prefab::ConfigDelta.new(key: "sample_int", default: Prefab::ConfigValue.new(int: 456)))
46
+ @loader.set(Prefab::Config.new(key: "sample_int", rows: [Prefab::ConfigRow.new(value: Prefab::ConfigValue.new(int: 456))]))
47
47
  should_be :int, 456, "sample_int"
48
48
  end
49
49
 
50
50
  def test_api_deltas
51
51
  val = Prefab::ConfigValue.new(int: 456)
52
- delta = Prefab::ConfigDelta.new(key: "sample_int", default: val)
53
- @loader.set(delta)
52
+ config = Prefab::Config.new(key: "sample_int", rows: [Prefab::ConfigRow.new(value: val)])
53
+ @loader.set(config)
54
54
 
55
- deltas = Prefab::ConfigDeltas.new
56
- deltas.deltas << delta
57
- assert_equal deltas, @loader.get_api_deltas
55
+ configs = Prefab::Configs.new
56
+ configs.configs << config
57
+ assert_equal configs, @loader.get_api_deltas
58
58
  end
59
59
 
60
60
  def test_loading_tombstones_removes_entries
61
61
  val = Prefab::ConfigValue.new(int: 456)
62
- delta = Prefab::ConfigDelta.new(key: "sample_int", default: val)
63
- @loader.set(delta)
62
+ config = Prefab::Config.new(key: "sample_int", rows: [Prefab::ConfigRow.new(value: val)])
63
+ @loader.set(config)
64
64
 
65
- delta = Prefab::ConfigDelta.new(key: "sample_int", default: nil)
66
- @loader.set(delta)
65
+ config = Prefab::Config.new(key: "sample_int", rows: [])
66
+ @loader.set(config)
67
67
 
68
- deltas = Prefab::ConfigDeltas.new
69
- assert_equal deltas, @loader.get_api_deltas
68
+ configs = Prefab::Configs.new
69
+ assert_equal configs, @loader.get_api_deltas
70
70
  end
71
71
 
72
72
  private
73
73
 
74
74
  def should_be(type, value, key)
75
- assert_equal type, @loader.calc_config[key].default.type
76
- assert_equal value, @loader.calc_config[key].default.send(type)
75
+ assert_equal type, @loader.calc_config[key].rows[0].value.type
76
+ assert_equal value, @loader.calc_config[key].rows[0].value.send(type)
77
77
  end
78
78
 
79
79
  end
@@ -6,35 +6,44 @@ class TestConfigResolver < Minitest::Test
6
6
  @loader = MockConfigLoader.new
7
7
 
8
8
  loaded_values = {
9
- "key" => Prefab::ConfigDelta.new(
9
+ "key" => Prefab::Config.new(
10
10
  key: "key",
11
- default: Prefab::ConfigValue.new(string: "value_no_env_default"),
12
- envs: [{
13
- environment: "test",
14
- default: Prefab::ConfigValue.new(string: "value_none"),
15
- namespace_values: [
16
- {
17
- namespace: "projectA",
18
- config_value: Prefab::ConfigValue.new(string: "valueA")
19
- },
20
- {
21
- namespace: "projectB",
22
- config_value: Prefab::ConfigValue.new(string: "valueB")
23
- },
24
- {
25
- namespace: "projectB.subprojectX",
26
- config_value: Prefab::ConfigValue.new(string: "projectB.subprojectX")
27
- },
28
- {
29
- namespace: "projectB.subprojectY",
30
- config_value: Prefab::ConfigValue.new(string: "projectB.subprojectY")
31
- },
32
- ]
33
- }]
11
+ rows: [
12
+ Prefab::ConfigRow.new(
13
+ value: Prefab::ConfigValue.new(string: "value_no_env_default"),
14
+ ),
15
+ Prefab::ConfigRow.new(
16
+ env_key: "test",
17
+ value: Prefab::ConfigValue.new(string: "value_none"),
18
+ ),
19
+ Prefab::ConfigRow.new(
20
+ env_key: "test",
21
+ namespace: "projectA",
22
+ value: Prefab::ConfigValue.new(string: "valueA"),
23
+ ),
24
+ Prefab::ConfigRow.new(
25
+ env_key: "test",
26
+ namespace: "projectB",
27
+ value: Prefab::ConfigValue.new(string: "valueB"),
28
+ ),
29
+ Prefab::ConfigRow.new(
30
+ env_key: "test",
31
+ namespace: "projectB.subprojectX",
32
+ value: Prefab::ConfigValue.new(string: "projectB.subprojectX"),
33
+ ),
34
+ Prefab::ConfigRow.new(
35
+ env_key: "test",
36
+ namespace: "projectB.subprojectY",
37
+ value: Prefab::ConfigValue.new(string: "projectB.subprojectY"),
38
+ ),
39
+
40
+ ]
34
41
  ),
35
- "key2" => Prefab::ConfigDelta.new(
42
+ "key2" => Prefab::Config.new(
36
43
  key: "key2",
37
- default: Prefab::ConfigValue.new(string: "valueB2"),
44
+ rows: [
45
+ value: Prefab::ConfigValue.new(string: "valueB2"),
46
+ ]
38
47
  )
39
48
  }
40
49
 
@@ -93,32 +102,31 @@ class TestConfigResolver < Minitest::Test
93
102
  def test_special_ff_variant_copying
94
103
  @loader = MockConfigLoader.new
95
104
  loaded_values = {
96
- "ff" => Prefab::ConfigDelta.new(
105
+ "ff" => Prefab::Config.new(
97
106
  key: "ff",
98
- default: Prefab::ConfigValue.new(feature_flag: Prefab::FeatureFlag.new(
99
- variants: [
100
- Prefab::FeatureFlagVariant.new(string: "inactive"),
101
- Prefab::FeatureFlagVariant.new(string: "default"),
102
- Prefab::FeatureFlagVariant.new(string: "env"),
103
- ],
104
- inactive_variant_idx: 0,
105
- default: Prefab::VariantDistribution.new(variant_idx: 1)
106
- )),
107
- envs: [
108
- Prefab::EnvironmentValues.new(
109
- environment: "test",
110
- default: Prefab::ConfigValue.new(feature_flag: Prefab::FeatureFlag.new(
107
+ variants: [
108
+ Prefab::FeatureFlagVariant.new(string: "inactive"),
109
+ Prefab::FeatureFlagVariant.new(string: "default"),
110
+ Prefab::FeatureFlagVariant.new(string: "env"),
111
+ ],
112
+ rows: [
113
+ { value: Prefab::ConfigValue.new(feature_flag: Prefab::FeatureFlag.new(
114
+ inactive_variant_idx: 0,
115
+ default: Prefab::VariantDistribution.new(variant_idx: 1)
116
+ )) },
117
+ { env_key: "test",
118
+ value: Prefab::ConfigValue.new(feature_flag: Prefab::FeatureFlag.new(
111
119
  inactive_variant_idx: 0,
112
- default: Prefab::VariantDistribution.new(variant_idx: 2)))
113
- )
120
+ default: Prefab::VariantDistribution.new(variant_idx: 2)
121
+ )) }
114
122
  ]
115
123
  )
116
124
  }
117
125
  @loader.stub :calc_config, loaded_values do
118
126
  resolver = Prefab::ConfigResolver.new(MockBaseClient.new, @loader)
119
- ff = resolver.get("ff")
120
- assert_equal 3, ff.variants.size
121
- assert_equal %w(inactive default env), ff.variants.map(&:string)
127
+ config = resolver.get_config("ff")
128
+ assert_equal 3, config.variants.size
129
+ assert_equal %w(inactive default env), config.variants.map(&:string)
122
130
  end
123
131
  end
124
132
 
@@ -127,13 +135,17 @@ class TestConfigResolver < Minitest::Test
127
135
  @loader = MockConfigLoader.new
128
136
 
129
137
  loaded_values = {
130
- "Key:With:Colons" => Prefab::ConfigDelta.new(
138
+ "Key:With:Colons" => Prefab::Config.new(
131
139
  key: "Key:With:Colons",
132
- default: Prefab::ConfigValue.new(string: "value"),
140
+ rows: [Prefab::ConfigRow.new(
141
+ value: Prefab::ConfigValue.new(string: "value")
142
+ )]
133
143
  ),
134
- "proj:apikey" => Prefab::ConfigDelta.new(
144
+ "proj:apikey" => Prefab::Config.new(
135
145
  key: "proj:apikey",
136
- default: Prefab::ConfigValue.new(string: "v2"),
146
+ rows: [Prefab::ConfigRow.new(
147
+ value: Prefab::ConfigValue.new(string: "v2")
148
+ )]
137
149
  )
138
150
  }
139
151
 
@@ -13,12 +13,12 @@ class TestFeatureFlagClient < Minitest::Test
13
13
  def test_pct
14
14
  feature = "FlagName"
15
15
 
16
+ variants = [
17
+ Prefab::FeatureFlagVariant.new(bool: false),
18
+ Prefab::FeatureFlagVariant.new(bool: true)
19
+ ]
16
20
  flag = Prefab::FeatureFlag.new(
17
21
  active: true,
18
- variants: [
19
- Prefab::FeatureFlagVariant.new(bool: false),
20
- Prefab::FeatureFlagVariant.new(bool: true)
21
- ],
22
22
  inactive_variant_idx: 0,
23
23
  default: Prefab::VariantDistribution.new(variant_weights:
24
24
  Prefab::VariantWeights.new(weights: [
@@ -32,52 +32,52 @@ class TestFeatureFlagClient < Minitest::Test
32
32
  )
33
33
 
34
34
  assert_equal false,
35
- @client.evaluate(feature, "hashes high", [], flag)
35
+ @client.evaluate(feature, "hashes high", [], flag, variants)
36
36
  assert_equal true,
37
- @client.evaluate(feature, "hashes low", [], flag)
37
+ @client.evaluate(feature, "hashes low", [], flag, variants)
38
38
  end
39
39
 
40
40
  def test_basic_active_inactive
41
41
  feature = "FlagName"
42
+ variants = [
43
+ Prefab::FeatureFlagVariant.new(bool: false),
44
+ Prefab::FeatureFlagVariant.new(bool: true)
45
+ ]
42
46
  flag = Prefab::FeatureFlag.new(
43
47
  active: true,
44
- variants: [
45
- Prefab::FeatureFlagVariant.new(bool: false),
46
- Prefab::FeatureFlagVariant.new(bool: true)
47
- ],
48
48
  inactive_variant_idx: 0,
49
49
  default: Prefab::VariantDistribution.new(variant_idx: 1)
50
50
  )
51
51
  assert_equal true,
52
- @client.evaluate(feature, "hashes high", [], flag)
52
+ @client.evaluate(feature, "hashes high", [], flag, variants)
53
53
  assert_equal true,
54
- @client.evaluate(feature, "hashes low", [], flag)
54
+ @client.evaluate(feature, "hashes low", [], flag, variants)
55
55
 
56
+ variants = [
57
+ Prefab::FeatureFlagVariant.new(bool: false),
58
+ Prefab::FeatureFlagVariant.new(bool: true)
59
+ ]
56
60
  flag = Prefab::FeatureFlag.new(
57
61
  active: false,
58
- variants: [
59
- Prefab::FeatureFlagVariant.new(bool: false),
60
- Prefab::FeatureFlagVariant.new(bool: true)
61
- ],
62
62
  inactive_variant_idx: 0,
63
63
  default: Prefab::VariantDistribution.new(variant_idx: 1)
64
64
  )
65
65
  assert_equal false,
66
- @client.evaluate(feature, "hashes high", [], flag)
66
+ @client.evaluate(feature, "hashes high", [], flag, variants)
67
67
  assert_equal false,
68
- @client.evaluate(feature, "hashes low", [], flag)
68
+ @client.evaluate(feature, "hashes low", [], flag, variants)
69
69
  end
70
70
 
71
71
  def test_user_targets
72
72
 
73
73
  feature = "FlagName"
74
+ variants = [
75
+ Prefab::FeatureFlagVariant.new(string: "inactive"),
76
+ Prefab::FeatureFlagVariant.new(string: "user target"),
77
+ Prefab::FeatureFlagVariant.new(string: "default"),
78
+ ]
74
79
  flag = Prefab::FeatureFlag.new(
75
80
  active: true,
76
- variants: [
77
- Prefab::FeatureFlagVariant.new(string: "inactive"),
78
- Prefab::FeatureFlagVariant.new(string: "user target"),
79
- Prefab::FeatureFlagVariant.new(string: "default"),
80
- ],
81
81
  inactive_variant_idx: 0,
82
82
  user_targets: [
83
83
  variant_idx: 1,
@@ -87,22 +87,22 @@ class TestFeatureFlagClient < Minitest::Test
87
87
  )
88
88
 
89
89
  assert_equal "user target",
90
- @client.evaluate(feature, "user:1", [], flag)
90
+ @client.evaluate(feature, "user:1", [], flag, variants)
91
91
  assert_equal "default",
92
- @client.evaluate(feature, "user:2", [], flag)
92
+ @client.evaluate(feature, "user:2", [], flag, variants)
93
93
  assert_equal "user target",
94
- @client.evaluate(feature, "user:3", [], flag)
94
+ @client.evaluate(feature, "user:3", [], flag, variants)
95
95
  end
96
96
 
97
97
  def test_inclusion_rule
98
98
  feature = "FlagName"
99
+ variants = [
100
+ Prefab::FeatureFlagVariant.new(string: "inactive"),
101
+ Prefab::FeatureFlagVariant.new(string: "rule target"),
102
+ Prefab::FeatureFlagVariant.new(string: "default"),
103
+ ]
99
104
  flag = Prefab::FeatureFlag.new(
100
105
  active: true,
101
- variants: [
102
- Prefab::FeatureFlagVariant.new(string: "inactive"),
103
- Prefab::FeatureFlagVariant.new(string: "rule target"),
104
- Prefab::FeatureFlagVariant.new(string: "default"),
105
- ],
106
106
  inactive_variant_idx: 0,
107
107
  rules: [Prefab::Rule.new(
108
108
  distribution: Prefab::VariantDistribution.new(variant_idx: 1),
@@ -115,9 +115,9 @@ class TestFeatureFlagClient < Minitest::Test
115
115
  )
116
116
 
117
117
  assert_equal "rule target",
118
- @client.evaluate(feature, "user:1", [], flag)
118
+ @client.evaluate(feature, "user:1", [], flag, variants)
119
119
  assert_equal "default",
120
- @client.evaluate(feature, "user:2", [], flag)
120
+ @client.evaluate(feature, "user:2", [], flag, variants)
121
121
 
122
122
  end
123
123
 
@@ -143,13 +143,13 @@ class TestFeatureFlagClient < Minitest::Test
143
143
  )
144
144
 
145
145
  feature = "FlagName"
146
+ variants = [
147
+ Prefab::FeatureFlagVariant.new(string: "inactive"),
148
+ Prefab::FeatureFlagVariant.new(string: "rule target"),
149
+ Prefab::FeatureFlagVariant.new(string: "default"),
150
+ ]
146
151
  flag = Prefab::FeatureFlag.new(
147
152
  active: true,
148
- variants: [
149
- Prefab::FeatureFlagVariant.new(string: "inactive"),
150
- Prefab::FeatureFlagVariant.new(string: "rule target"),
151
- Prefab::FeatureFlagVariant.new(string: "default"),
152
- ],
153
153
  inactive_variant_idx: 0,
154
154
  rules: [Prefab::Rule.new(
155
155
  distribution: Prefab::VariantDistribution.new(variant_idx: 1),
@@ -162,9 +162,9 @@ class TestFeatureFlagClient < Minitest::Test
162
162
  )
163
163
 
164
164
  assert_equal "rule target",
165
- @client.evaluate(feature, "user:1", [], flag)
165
+ @client.evaluate(feature, "user:1", [], flag, variants)
166
166
  assert_equal "default",
167
- @client.evaluate(feature, "user:2", [], flag)
167
+ @client.evaluate(feature, "user:2", [], flag, variants)
168
168
 
169
169
  end
170
170
 
@@ -187,13 +187,13 @@ class TestFeatureFlagClient < Minitest::Test
187
187
  )
188
188
 
189
189
  feature = "FlagName"
190
+ variants = [
191
+ Prefab::FeatureFlagVariant.new(string: "inactive"),
192
+ Prefab::FeatureFlagVariant.new(string: "rule target"),
193
+ Prefab::FeatureFlagVariant.new(string: "default"),
194
+ ]
190
195
  flag = Prefab::FeatureFlag.new(
191
196
  active: true,
192
- variants: [
193
- Prefab::FeatureFlagVariant.new(string: "inactive"),
194
- Prefab::FeatureFlagVariant.new(string: "rule target"),
195
- Prefab::FeatureFlagVariant.new(string: "default"),
196
- ],
197
197
  inactive_variant_idx: 0,
198
198
  rules: [Prefab::Rule.new(
199
199
  distribution: Prefab::VariantDistribution.new(variant_idx: 1),
@@ -206,15 +206,15 @@ class TestFeatureFlagClient < Minitest::Test
206
206
  )
207
207
 
208
208
  assert_equal "rule target",
209
- @client.evaluate(feature, "user:1", [], flag)
209
+ @client.evaluate(feature, "user:1", [], flag, variants)
210
210
  assert_equal "rule target",
211
- @client.evaluate(feature, "user:2", [], flag), "matches segment 1"
211
+ @client.evaluate(feature, "user:2", [], flag, variants), "matches segment 1"
212
212
  assert_equal "rule target",
213
- @client.evaluate(feature, "user:3", [], flag)
213
+ @client.evaluate(feature, "user:3", [], flag, variants)
214
214
  assert_equal "rule target",
215
- @client.evaluate(feature, "user:4", [], flag)
215
+ @client.evaluate(feature, "user:4", [], flag, variants)
216
216
  assert_equal "default",
217
- @client.evaluate(feature, "user:5", [], flag)
217
+ @client.evaluate(feature, "user:5", [], flag, variants)
218
218
 
219
219
  end
220
220
  end
data/test/test_helper.rb CHANGED
@@ -25,6 +25,11 @@ class MockBaseClient
25
25
  def get(key)
26
26
  @config_values[key]
27
27
  end
28
+
29
+ def get_config(key)
30
+ puts "HELLOOOO"
31
+ @config_values[key]
32
+ end
28
33
  end
29
34
 
30
35
  class MockConfigLoader
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.8.0
4
+ version: 0.9.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-02-24 00:00:00.000000000 Z
11
+ date: 2022-03-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -44,6 +44,20 @@ dependencies:
44
44
  - - ">="
45
45
  - !ruby/object:Gem::Version
46
46
  version: '0'
47
+ - !ruby/object:Gem::Dependency
48
+ name: ld-eventsource
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
47
61
  - !ruby/object:Gem::Dependency
48
62
  name: grpc
49
63
  requirement: !ruby/object:Gem::Requirement