splitclient-rb 3.1.2 → 3.1.3.pre.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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