splitclient-rb 3.1.2 → 3.1.3.pre.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES.txt +7 -0
  3. data/Detailed-README.md +20 -5
  4. data/exe/splitio +54 -3
  5. data/lib/cache/adapters/memory_adapters/map_adapter.rb +6 -0
  6. data/lib/cache/adapters/redis_adapter.rb +6 -1
  7. data/lib/cache/repositories/impressions/memory_repository.rb +8 -2
  8. data/lib/cache/repositories/impressions/redis_repository.rb +2 -2
  9. data/lib/cache/repositories/impressions_repository.rb +3 -0
  10. data/lib/cache/repositories/metrics_repository.rb +1 -0
  11. data/lib/cache/repositories/repository.rb +1 -1
  12. data/lib/cache/repositories/segments_repository.rb +16 -1
  13. data/lib/cache/repositories/splits_repository.rb +21 -7
  14. data/lib/cache/senders/impressions_sender.rb +16 -12
  15. data/lib/cache/senders/metrics_sender.rb +41 -0
  16. data/lib/cache/stores/sdk_blocker.rb +9 -8
  17. data/lib/cache/stores/segment_store.rb +1 -1
  18. data/lib/engine/api/client.rb +15 -2
  19. data/lib/engine/api/metrics.rb +57 -0
  20. data/lib/engine/parser/split_adapter.rb +9 -140
  21. data/lib/engine/parser/split_treatment.rb +7 -5
  22. data/lib/engine/partitions/treatments.rb +1 -5
  23. data/lib/splitclient-rb.rb +14 -4
  24. data/lib/splitclient-rb/clients/localhost_split_client.rb +89 -0
  25. data/lib/splitclient-rb/clients/split_client.rb +114 -0
  26. data/lib/splitclient-rb/localhost_split_factory.rb +6 -187
  27. data/lib/splitclient-rb/localhost_utils.rb +36 -0
  28. data/lib/splitclient-rb/managers/localhost_split_manager.rb +45 -0
  29. data/lib/splitclient-rb/managers/split_manager.rb +77 -0
  30. data/lib/splitclient-rb/split_config.rb +20 -0
  31. data/lib/splitclient-rb/split_factory.rb +16 -217
  32. data/lib/splitclient-rb/split_factory_builder.rb +3 -2
  33. data/lib/splitclient-rb/version.rb +1 -1
  34. data/lib/splitclient-rb_utilitites.rb +24 -19
  35. data/splitclient-rb.gemspec +1 -1
  36. data/{splitio.yml → splitio.yml.example} +0 -0
  37. metadata +26 -19
@@ -29,6 +29,7 @@ module SplitIoClient
29
29
  @events_uri = (opts[:events_uri] || SplitConfig.default_events_uri).chomp('/')
30
30
  @mode = opts[:mode] || SplitConfig.default_mode
31
31
  @redis_url = opts[:redis_url] || SplitConfig.default_redis_url
32
+ @redis_namespace = opts[:redis_namespace] || SplitConfig.default_redis_namespace
32
33
  @cache_adapter = SplitConfig.init_cache_adapter(
33
34
  opts[:cache_adapter] || SplitConfig.default_cache_adapter, :map_adapter, @redis_url, false
34
35
  )
@@ -145,6 +146,7 @@ module SplitIoClient
145
146
  attr_reader :impressions_queue_size
146
147
 
147
148
  attr_reader :redis_url
149
+ attr_reader :redis_namespace
148
150
 
149
151
  #
150
152
  # The default split client configuration
@@ -154,6 +156,14 @@ module SplitIoClient
154
156
  SplitConfig.new
155
157
  end
156
158
 
159
+ #
160
+ # method that returns the sdk gem version
161
+ #
162
+ # @return [string] version value for this sdk
163
+ def self.sdk_version
164
+ 'RubyClientSDK-'+SplitIoClient::VERSION
165
+ end
166
+
157
167
  #
158
168
  # The default base uri for api calls
159
169
  #
@@ -176,6 +186,12 @@ module SplitIoClient
176
186
 
177
187
  SplitIoClient::Cache::Adapters::MemoryAdapter.new(adapter)
178
188
  when :redis
189
+ begin
190
+ require 'redis'
191
+ rescue LoadError
192
+ fail StandardError, 'To use Redis as a cache adapter you must include it in your Gemfile'
193
+ end
194
+
179
195
  SplitIoClient::Cache::Adapters::RedisAdapter.new(redis_url)
180
196
  end
181
197
  end
@@ -249,6 +265,10 @@ module SplitIoClient
249
265
  'redis://127.0.0.1:6379/0'
250
266
  end
251
267
 
268
+ def self.default_redis_namespace
269
+ "SPLITIO/ruby-#{VERSION}"
270
+ end
271
+
252
272
  #
253
273
  # The default transport_debug_enabled value
254
274
  #
@@ -1,229 +1,28 @@
1
- require 'logger'
2
-
3
1
  module SplitIoClient
4
- #
5
- # main class for split client sdk
6
- #
7
- class SplitFactory < NoMethodError
8
- class SplitManager < NoMethodError
9
- #
10
- # Creates a new split manager instance that connects to split.io API.
11
- #
12
- # @param api_key [String] the API key for your split account
13
- #
14
- # @return [SplitIoManager] split.io client instance
15
- def initialize(api_key, config = {}, adapter = nil, splits_repository = nil)
16
- @localhost_mode_features = []
17
- @config = config
18
- @splits_repository = splits_repository
19
- @adapter = adapter
20
- end
21
-
22
- #
23
- # method to get the split list from the client
24
- #
25
- # @returns [object] array of splits
26
- def splits
27
- return if @splits_repository.nil?
28
-
29
- @splits_repository.splits.each_with_object([]) do |(name, split), memo|
30
- split_model = Engine::Models::Split.new(split)
31
-
32
- memo << build_split_view(name, split) unless split_model.archived?
33
- end
34
- end
35
-
36
- #
37
- # method to get the list of just split names. Ideal for ietrating and calling client.get_treatment
38
- #
39
- # @returns [object] array of split names (String)
40
- def split_names
41
- return if @splits_repository.nil?
42
-
43
- @splits_repository.split_names
44
- end
45
-
46
- #
47
- # method to get a split view
48
- #
49
- # @returns a split view
50
- def split(split_name)
51
- if @splits_repository
52
- split = @splits_repository.get_split(split_name)
53
-
54
- build_split_view(split_name, split) unless split.nil? or split_model(split).archived?
55
- end
56
- end
57
-
58
- def build_split_view(name, split)
59
- treatments = split[:conditions] && split[:conditions][0][:partitions] \
60
- ? split[:conditions][0][:partitions].map{ |partition| partition[:treatment] }
61
- : []
62
- {
63
- name: name,
64
- traffic_type_name: split[:trafficTypeName],
65
- killed: split[:killed],
66
- treatments: treatments,
67
- change_number: split[:changeNumber]
68
- }
69
- end
70
-
71
- private
72
-
73
- def split_model(split)
74
- split_model = Engine::Models::Split.new(split)
75
- end
76
- end
77
-
78
- class SplitClient < NoMethodError
79
- #
80
- # Creates a new split client instance that connects to split.io API.
81
- #
82
- # @param api_key [String] the API key for your split account
83
- #
84
- # @return [SplitIoClient] split.io client instance
85
- def initialize(api_key, config = {}, adapter = nil, splits_repository, segments_repository, impressions_repository, metrics_repository)
86
- @config = config
87
-
88
- @splits_repository = splits_repository
89
- @segments_repository = segments_repository
90
- @impressions_repository = impressions_repository
91
- @metrics_repository = metrics_repository
92
-
93
- @adapter = adapter
94
- end
95
-
96
- def get_treatments(key, split_names, attributes = nil)
97
- bucketing_key, matching_key = keys_from_key(key)
98
- bucketing_key = matching_key if bucketing_key.nil?
99
-
100
- treatments = @splits_repository.get_splits(split_names).each_with_object({}) do |(name, data), memo|
101
- memo.merge!(name => get_treatment(key, name, attributes, data, false))
102
- end
103
-
104
- if @config.impressions_queue_size > 0
105
- @impressions_repository.add_bulk(matching_key, treatments, (Time.now.to_f * 1000.0).to_i)
106
- end
107
-
108
- treatments
109
- end
110
-
111
- #
112
- # obtains the treatment for a given feature
113
- #
114
- # @param key [String/Hash] user id or hash with matching_key/bucketing_key
115
- # @param split_name [String/Array] name of the feature that is being validated or array of them
116
- #
117
- # @return [String/Hash] Treatment as String or Hash of treatments in case of array of features
118
- def get_treatment(key, split_name, attributes = nil, split_data = nil, store_impressions = true)
119
- bucketing_key, matching_key = keys_from_key(key)
120
- bucketing_key = matching_key if bucketing_key.nil?
121
-
122
- if matching_key.nil?
123
- @config.logger.warn('matching_key was null for split_name: ' + split_name.to_s)
124
- return Treatments::CONTROL
125
- end
126
-
127
- if split_name.nil?
128
- @config.logger.warn('split_name was null for key: ' + key)
129
- return Treatments::CONTROL
130
- end
2
+ class SplitFactory
3
+ include SplitIoClient::Cache::Repositories
4
+ include SplitIoClient::Cache::Stores
131
5
 
132
- start = Time.now
133
- result = nil
6
+ attr_reader :adapter, :client, :manager
134
7
 
135
- begin
136
- split = split_data ? split_data : @splits_repository.get_split(split_name)
137
-
138
- result = if split.nil?
139
- Treatments::CONTROL
140
- else
141
- SplitIoClient::Engine::Parser::SplitTreatment.new(@segments_repository).call(
142
- { bucketing_key: bucketing_key, matching_key: matching_key }, split, attributes
143
- )
144
- end
145
- rescue StandardError => error
146
- @config.log_found_exception(__method__.to_s, error)
147
- end
148
-
149
- result = result.nil? ? Treatments::CONTROL : result
150
-
151
- begin
152
- latency = (Time.now - start) * 1000.0
153
- if @config.impressions_queue_size > 0 && store_impressions
154
- # Disable impressions if @config.impressions_queue_size == -1
155
- @impressions_repository.add(split_name, 'key_name' => matching_key, 'treatment' => result, 'time' => (Time.now.to_f * 1000.0).to_i)
156
- end
157
-
158
- # Measure
159
- @adapter.metrics.time("sdk.get_treatment", latency)
160
- rescue StandardError => error
161
- @config.log_found_exception(__method__.to_s, error)
162
- end
163
-
164
- result
165
- end
166
-
167
- def keys_from_key(key)
168
- case key.class.to_s
169
- when 'Hash'
170
- key.values_at(:bucketing_key, :matching_key)
171
- when 'String'
172
- [key, key]
173
- end
174
- end
175
-
176
- #
177
- # method that returns the sdk gem version
178
- #
179
- # @return [string] version value for this sdk
180
- def self.sdk_version
181
- 'ruby-'+SplitIoClient::VERSION
182
- end
183
- end
184
-
185
- private_constant :SplitClient
186
- private_constant :SplitManager
187
-
188
- def initialize(api_key, config = {})
8
+ def initialize(api_key, config_hash = {})
189
9
  @api_key = api_key
190
- @config = SplitConfig.new(config)
191
- @cache_adapter = @config.cache_adapter
192
- @splits_repository = SplitIoClient::Cache::Repositories::SplitsRepository.new(@cache_adapter)
193
- @segments_repository = SplitIoClient::Cache::Repositories::SegmentsRepository.new(@cache_adapter)
194
- @impressions_repository = SplitIoClient::Cache::Repositories::ImpressionsRepository.new(@config.impressions_adapter, @config)
195
- @metrics_repository = SplitIoClient::Cache::Repositories::MetricsRepository.new(@config.metrics_adapter, @config)
196
- @sdk_blocker = SplitIoClient::Cache::Stores::SDKBlocker.new(@config)
197
- @adapter = SplitAdapter.new(api_key, @config, @splits_repository, @segments_repository, @impressions_repository, @metrics_repository, @sdk_blocker)
10
+ @config = SplitConfig.new(config_hash)
198
11
 
199
- @sdk_blocker.block if @config.block_until_ready
200
- end
201
-
202
- def client
203
- @client ||= init_client
204
- end
205
-
206
- def manager
207
- @manager ||= init_manager
208
- end
12
+ @cache_adapter = @config.cache_adapter
209
13
 
210
- #
211
- # method that returns the sdk gem version
212
- #
213
- # @return [string] version value for this sdk
214
- def self.sdk_version
215
- 'RubyClientSDK-'+SplitIoClient::VERSION
216
- end
14
+ @splits_repository = SplitsRepository.new(@cache_adapter, @config)
15
+ @segments_repository = SegmentsRepository.new(@cache_adapter, @config)
16
+ @impressions_repository = ImpressionsRepository.new(@config.impressions_adapter, @config)
17
+ @metrics_repository = MetricsRepository.new(@config.metrics_adapter, @config)
217
18
 
218
- private
219
- attr_reader :adapter
19
+ @sdk_blocker = SDKBlocker.new(@config, @splits_repository, @segments_repository)
20
+ @adapter = SplitAdapter.new(@api_key, @config, @splits_repository, @segments_repository, @impressions_repository, @metrics_repository, @sdk_blocker)
220
21
 
221
- def init_client
222
- SplitClient.new(@api_key, @config, @adapter, @splits_repository, @segments_repository, @impressions_repository, @metrics_repository)
223
- end
22
+ @client = SplitClient.new(@api_key, @config, @adapter, @splits_repository, @segments_repository, @impressions_repository, @metrics_repository)
23
+ @manager = SplitManager.new(@api_key, @config, @adapter, @splits_repository)
224
24
 
225
- def init_manager
226
- SplitManager.new(@api_key, @config, @adapter, @splits_repository)
25
+ @sdk_blocker.block if @config.block_until_ready
227
26
  end
228
27
  end
229
28
  end
@@ -1,12 +1,13 @@
1
+ require 'logger'
2
+
1
3
  module SplitIoClient
2
4
  class SplitFactoryBuilder
3
5
  def self.build(api_key, config = {})
4
6
  case api_key
5
7
  when 'localhost'
6
8
  splits_file = config[:path]? config[:path] : File.join(Dir.home, '.split')
7
- puts("Filename #{splits_file}")
8
9
 
9
- LocalhostSplitFactory.new(splits_file)
10
+ LocalhostSplitFactory.new(splits_file, config[:reload_rate])
10
11
  else
11
12
  SplitFactory.new(api_key, config)
12
13
  end
@@ -1,3 +1,3 @@
1
1
  module SplitIoClient
2
- VERSION = '3.1.2'
2
+ VERSION = '3.1.3-rc1'
3
3
  end
@@ -2,33 +2,38 @@ module Utilities
2
2
  extend self
3
3
 
4
4
  # Convert String with Time info to its epoch FixNum previously setting to zero the seconds
5
- def to_epoch value
5
+ def to_epoch(value)
6
6
  parsed = Time.parse(value)
7
7
  zeroed = Time.new(parsed.year, parsed.month, parsed.day, parsed.hour, parsed.min, 0, 0)
8
+
8
9
  zeroed.to_i
9
10
  end
10
11
 
11
- def to_epoch_milis value
12
- (to_epoch (value)) * 1000
12
+ def to_epoch_milis(value)
13
+ to_epoch(value) * 1000
14
+ end
15
+
16
+ def to_milis_zero_out_from_seconds(value)
17
+ parsed_value = Time.strptime(value.to_s, '%s').utc
18
+ zeroed = Time.new(parsed_value.year, parsed_value.month, parsed_value.day, parsed_value.hour, parsed_value.min, 0, 0)
19
+
20
+ zeroed.to_i * 1000
21
+ rescue
22
+ return :non_valid_date_info
13
23
  end
14
24
 
15
- def to_milis_zero_out_from_seconds value
16
- begin
17
- parsed_value = Time.strptime(value.to_s,'%s').utc
18
- zeroed = Time.new(parsed_value.year, parsed_value.month, parsed_value.day, parsed_value.hour, parsed_value.min, 0, 0)
19
- return zeroed.to_i*1000
20
- rescue
21
- return :non_valid_date_info
22
- end
25
+ def to_milis_zero_out_from_hour(value)
26
+ parsed_value = Time.strptime(value.to_s, '%s').utc
27
+ zeroed = Time.new(parsed_value.year, parsed_value.month, parsed_value.day, 0, 0, 0, 0)
28
+
29
+ zeroed.to_i * 1000
30
+ rescue StandardError
31
+ return :non_valid_date_info
23
32
  end
24
33
 
25
- def to_milis_zero_out_from_hour value
26
- begin
27
- parsed_value = Time.strptime(value.to_s,'%s').utc
28
- zeroed = Time.new(parsed_value.year, parsed_value.month, parsed_value.day, 0, 0, 0, 0)
29
- return zeroed.to_i*1000
30
- rescue
31
- return :non_valid_date_info
32
- end
34
+ def randomize_interval(interval)
35
+ random_factor = Random.new.rand(50..100) / 100.0
36
+
37
+ interval * random_factor
33
38
  end
34
39
  end
@@ -27,6 +27,7 @@ Gem::Specification.new do |spec|
27
27
  spec.add_development_dependency "pry"
28
28
  spec.add_development_dependency "pry-byebug"
29
29
  spec.add_development_dependency "simplecov"
30
+ spec.add_development_dependency "redis"
30
31
 
31
32
  spec.add_runtime_dependency "json", "~> 1.8"
32
33
  spec.add_runtime_dependency "thread_safe"
@@ -35,5 +36,4 @@ Gem::Specification.new do |spec|
35
36
  spec.add_runtime_dependency "faraday-http-cache"
36
37
  spec.add_runtime_dependency "faraday_middleware"
37
38
  spec.add_runtime_dependency "net-http-persistent", "<= 2.9.4"
38
- spec.add_runtime_dependency "redis", "~> 3.2"
39
39
  end
File without changes
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: splitclient-rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.2
4
+ version: 3.1.3.pre.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Split Software
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-11-21 00:00:00.000000000 Z
11
+ date: 2016-12-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -122,6 +122,20 @@ dependencies:
122
122
  - - ">="
123
123
  - !ruby/object:Gem::Version
124
124
  version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: redis
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
125
139
  - !ruby/object:Gem::Dependency
126
140
  name: json
127
141
  requirement: !ruby/object:Gem::Requirement
@@ -220,20 +234,6 @@ dependencies:
220
234
  - - "<="
221
235
  - !ruby/object:Gem::Version
222
236
  version: 2.9.4
223
- - !ruby/object:Gem::Dependency
224
- name: redis
225
- requirement: !ruby/object:Gem::Requirement
226
- requirements:
227
- - - "~>"
228
- - !ruby/object:Gem::Version
229
- version: '3.2'
230
- type: :runtime
231
- prerelease: false
232
- version_requirements: !ruby/object:Gem::Requirement
233
- requirements:
234
- - - "~>"
235
- - !ruby/object:Gem::Version
236
- version: '3.2'
237
237
  description: Ruby client for using split SDK.
238
238
  email:
239
239
  - pato@split.io
@@ -267,11 +267,13 @@ files:
267
267
  - lib/cache/repositories/splits_repository.rb
268
268
  - lib/cache/senders/impressions_formatter.rb
269
269
  - lib/cache/senders/impressions_sender.rb
270
+ - lib/cache/senders/metrics_sender.rb
270
271
  - lib/cache/stores/sdk_blocker.rb
271
272
  - lib/cache/stores/segment_store.rb
272
273
  - lib/cache/stores/split_store.rb
273
274
  - lib/engine/api/client.rb
274
275
  - lib/engine/api/impressions.rb
276
+ - lib/engine/api/metrics.rb
275
277
  - lib/engine/api/segments.rb
276
278
  - lib/engine/api/splits.rb
277
279
  - lib/engine/evaluator/splitter.rb
@@ -295,14 +297,19 @@ files:
295
297
  - lib/engine/partitions/treatments.rb
296
298
  - lib/exceptions/sdk_blocker_timeout_expired_exception.rb
297
299
  - lib/splitclient-rb.rb
300
+ - lib/splitclient-rb/clients/localhost_split_client.rb
301
+ - lib/splitclient-rb/clients/split_client.rb
298
302
  - lib/splitclient-rb/localhost_split_factory.rb
303
+ - lib/splitclient-rb/localhost_utils.rb
304
+ - lib/splitclient-rb/managers/localhost_split_manager.rb
305
+ - lib/splitclient-rb/managers/split_manager.rb
299
306
  - lib/splitclient-rb/split_config.rb
300
307
  - lib/splitclient-rb/split_factory.rb
301
308
  - lib/splitclient-rb/split_factory_builder.rb
302
309
  - lib/splitclient-rb/version.rb
303
310
  - lib/splitclient-rb_utilitites.rb
304
311
  - splitclient-rb.gemspec
305
- - splitio.yml
312
+ - splitio.yml.example
306
313
  - tasks/benchmark_get_treatment.rake
307
314
  - tasks/console.rake
308
315
  - tasks/rspec.rake
@@ -321,9 +328,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
321
328
  version: '0'
322
329
  required_rubygems_version: !ruby/object:Gem::Requirement
323
330
  requirements:
324
- - - ">="
331
+ - - ">"
325
332
  - !ruby/object:Gem::Version
326
- version: '0'
333
+ version: 1.3.1
327
334
  requirements: []
328
335
  rubyforge_project:
329
336
  rubygems_version: 2.5.2