prefab-cloud-ruby 0.8.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
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