splitclient-rb 3.1.0.pre.rc12 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/NEWS CHANGED
@@ -1,6 +1,7 @@
1
1
  3.1.0
2
2
 
3
3
  Now supporting Redis as a cache adapter
4
+ Factory is build now as SplitIoClient::SplitFactoryBuilder.build('<API_KEY>')
4
5
 
5
6
  3.0.2
6
7
 
data/README.md CHANGED
@@ -1,364 +1,52 @@
1
1
  # Split Ruby SDK
2
2
 
3
- Ruby SDK for Split software, provided as a gem that can be installed to your Ruby application.
3
+ This SDK is designed to work with [Split](https://www.split.io), the platform for controlled rollouts, serving features to your users via the Split feature flag to manage your complete customer experience.
4
4
 
5
- ## Installation
6
- ---
5
+ ### Quick setup
7
6
 
8
- - Once the gem is published you can install it with the following steps:
7
+ For specific instructions on how to set up the Ruby SDK refer to our [Detailed-README](Detailed-README.md) or our [official SDK documentation](http://docs.split.io/docs/sdk-overview).
9
8
 
10
- Add this line to your application's Gemfile:
9
+ ### Commitment to Quality:
11
10
 
12
- ```ruby
13
- gem 'splitclient-rb'
14
- ```
11
+ Split’s SDKs are in active development and are constantly tested for quality. Unit tests are developed for each SDK based on the unique needs of that language, and integration tests, load and performance tests, and behavior consistency tests are running 24/7 via automated bots. In addition, monitoring instrumentation ensures that these SDKs behave under the expected parameters of memory, CPU, and I/O.
15
12
 
16
- And then execute:
13
+ ### About Split:
17
14
 
18
- $ bundle install
15
+ Split builds on feature flags to create the platform for controlled rollouts, so any team can target customers and release or revert new features without a deployment—or touching code. Get started quickly with SDKs in your language, then create on/off, percentage, and multivariate rollout plans in seconds. Integrations with the services you use to monitor, alert and track issues reduce time-to-resolution when things go wrong, and hotfixes are entirely avoided by killing problem features with a single click.
19
16
 
20
- Or install it yourself as:
17
+ * What you can do with Split. Split goes beyond the simple on/off capabilities of basic feature flagging to give your team the power to:
21
18
 
22
- $ gem install splitclient-rb
19
+ * Create multivariate feature releases
20
+ * Create A/B feature releases
21
+ * Kill any feature, over the browser, with a single click
22
+ * Target releases to subsets of your audience, including percentage roll outs, whitelists, attribute-based targeting, and individual user IDs
23
+ * Integrate with the services your team uses to monitor, plan and communicate, like Datadog, JIRA and Slack
24
+ * Manage team access, with features like two-factor authentication and role-based permissioning.
23
25
 
24
- - You can also use the most recent version from github:
25
26
 
26
- Add these lines to you application's `Gemfile`:
27
- ```ruby
28
- gem 'splitclient-rb', git: 'https://github.com/splitio/ruby-client.git',
29
- ```
30
- You can also use any specific branch if necessary:
31
- ```ruby
32
- gem 'splitclient-rb', git: 'https://github.com/splitio/ruby-client.git', branch: 'development'
33
- ```
34
- And then execute:
27
+ Split has built and maintains a SDKs for:
35
28
 
36
- $ bundle install
29
+ * Java [Docs](http://docs.split.io/docs/java-sdk-guide)
30
+ * Javascript [Github](https://github.com/splitio/javascript-client) [Docs](http://docs.split.io/docs/javascript-sdk-overview)
31
+ * Node [Github](https://github.com/splitio/javascript-client) [Docs](http://docs.split.io/docs/nodejs-sdk-overview)
32
+ * .NET [Github](https://github.com/splitio/.net-client) [Docs](http://docs.split.io/docs/net-sdk-overview)
33
+ * Ruby [Github](https://github.com/splitio/ruby-client) [Docs](http://docs.split.io/docs/ruby-sdk-overview)
34
+ * PHP [Github](https://github.com/splitio/php-client) [Docs](http://docs.split.io/docs/php-sdk-overview)
35
+ * Python [Github](https://github.com/splitio/python-client) [Docs](http://docs.split.io/docs/python-sdk-overview)
37
36
 
38
- ## Usage
37
+ For a comprenhensive list of opensource projects visit our [Github page](https://github.com/splitio?utf8=%E2%9C%93&query=%20only%3Apublic%20).
39
38
 
40
- ### Quick Setup
41
- ---
39
+ **Try Split for Free:**
42
40
 
43
- Within your application you need the following:
41
+ Split is available as a 30-day free trial. To create an account, visit [split.io/trial](https://www.split.io/trial).
44
42
 
45
- Require the Split client:
46
- ```ruby
47
- require 'splitclient-rb'
48
- ```
43
+ **Learn more about Split:**
49
44
 
50
- Create a new split client instance with your API key:
51
- ```ruby
52
- factory = SplitIoClient::SplitFactory.new('YOUR_API_KEY').client
53
- split_client = factory.client
54
- ```
45
+ Visit [split.io/product](https://www.split.io/product) for an overview of Split, or visit our documentation at [docs.split.io](http://docs.split.io) for more detailed information.
55
46
 
56
- For advance use cases you can also obtain a `manager` instance from the factory.
57
- ```ruby
58
- manager = factory.manager
59
- ```
47
+ **System Status:**
60
48
 
61
- ### Ruby on Rails
62
- ---
49
+ We use a status page to monitor the availability of Split’s various services. You can check the current status at [status.split.io](http://status.split.io).
63
50
 
64
- Create an initializer: `config/initializers/splitclient.rb` and then initialize the split client:
65
- ```ruby
66
- Rails.configuration.split_client = SplitIoClient::SplitFactory.new('YOUR_API_KEY').client
67
- ```
68
- In your controllers, access the client using:
51
+ ----
69
52
 
70
- ```ruby
71
- Rails.application.config.split_client
72
- ```
73
-
74
- ### Configuration
75
- ---
76
-
77
- Split client's default configuration should be sufficient for most scenarios. However you can also provide custom configuration when initializing the client using an optional hash of options.
78
-
79
- The following values can be customized:
80
-
81
- **base_uri** : URI for the api endpoints
82
-
83
- *defualt value* = `https://sdk.split.io/api/`
84
-
85
- **connection_timeout** : timeout for network connections in seconds
86
-
87
- *default value* = `5`
88
-
89
- **read_timeout** : timeout for requests in seconds
90
-
91
- *default value* = `5`
92
-
93
- **features_refresh_rate** : The SDK polls Split servers for changes to feature roll-out plans. This parameter controls this polling period in seconds
94
-
95
- *default value* = `30`
96
-
97
- **segments_refresh_rate** : The SDK polls Split servers for changes to segment definitions. This parameter controls this polling period in seconds
98
-
99
- *default value* = `60`
100
-
101
- **metrics_refresh_rate** : The SDK sends diagnostic metrics to Split servers. This parameters controls this metric flush period in seconds
102
-
103
- *default value* = `60`
104
-
105
- **impressions_refresh_rate** : The SDK sends information on who got what treatment at what time back to Split servers to power analytics. This parameter controls how often this data is sent to Split servers in seconds
106
-
107
- **impressions_queue_size** : The size of the impressions queue in case of `cache_adapter == :memory` and the size impressions batch to be fetched from Redis in case of `cache_adapter == :redis`. Use `-1` to disable impressions.
108
-
109
- *default value* = `60`
110
-
111
- **debug_enabled** : Enables extra logging
112
-
113
- *default value* = `false`
114
-
115
- **transport_debug_enabled** : Enables extra transport logging
116
-
117
- *default value* = `false`
118
-
119
- **logger** : default logger for messages and errors
120
-
121
- *default value* = `Logger.new($stdout)`
122
-
123
- **block_until_ready** : The SDK will block your app for provided amount of seconds until it's ready. If timeout expires `SplitIoClient::SDKBlockerTimeoutExpiredException` will be thrown. If `false` provided, then SDK would run in non-blocking mode
124
-
125
- *default value* = `false`
126
-
127
- **mode** : See [SDK modes section](#sdk-modes).
128
-
129
- *default value* = `:standalone`
130
-
131
- #### Cache adapter
132
-
133
- The SDK needs some container to store data, i.e. splits/segments/impressions. By default it will store everything in the application's memory, but you can also use Redis.
134
-
135
- To use Redis, you have to include `redis-rb` in your app's Gemfile.
136
-
137
- **cache_adapter** : Supported options: `:memory`, `:redis`
138
-
139
- *default value* = `memory`
140
-
141
- **redis_url** : Redis URL or hash with configuration for SDK to connect to.
142
-
143
- *default value* = `'redis://127.0.0.1:6379/0'`
144
-
145
- You can also use Sentinel like this:
146
-
147
- ```ruby
148
- SENTINELS = [{host: '127.0.0.1', port: 26380},
149
- {host: '127.0.0.1', port: 26381}]
150
-
151
- redis_url = Redis.new(url: 'redis://mymaster', sentinels: SENTINELS, role: :master)
152
- ```
153
-
154
- Example using Redis
155
- ```ruby
156
- options = {
157
- connection_timeout: 10,
158
- read_timeout: 5,
159
- features_refresh_rate: 120,
160
- segments_refresh_rate: 120,
161
- metrics_refresh_rate: 360,
162
- impressions_refresh_rate: 360,
163
- logger: Logger.new('logfile.log'),
164
- block_until_ready: 5,
165
- cache_adapter: :redis,
166
- mode: :standalone,
167
- redis_url: 'redis://127.0.0.1:6379/0'
168
- }
169
- begin
170
- split_client = SplitIoClient::SplitFactory.new('YOUR_API_KEY', options).client
171
- rescue SplitIoClient::SDKBlockerTimeoutExpiredException
172
- # Some arbitrary actions
173
- end
174
- ```
175
-
176
- #### IMPORTANT
177
- For now, SDK does not support both `producer` mode and `block_until_ready`. You must either run SDK in `standalone` mode, or do not use `block_until_ready` option.
178
-
179
- This begin-rescue-end block is optional, you might want to use it to catch timeout expired exception and apply some logic.
180
-
181
- ### Execution
182
- ---
183
-
184
- In your application code you just need to call the `get_treatment` method with the required parameters for key and feature name:
185
- ```ruby
186
- split_client.get_treatment('user_id','feature_name', attr: 'val')
187
- ```
188
-
189
- For example
190
- ```ruby
191
- if split_client.get_treatment('employee_user_01','view_main_list', age: 35)
192
- my_app.display_main_list
193
- end
194
- ```
195
-
196
- Also, you can use different keys for actually getting treatment and sending impressions to the server:
197
- ```ruby
198
- split_client.get_treatment(
199
- { matching_key: 'user_id', bucketing_key: 'private_user_id' },
200
- 'feature_name',
201
- attr: 'val'
202
- )
203
- ```
204
- When it might be useful? Say, you have a user browsing your website and not signed up yet. You assign some internal id to that user (i.e. bucketing_key) and after user signs up you assign him a matching_key.
205
- By doing this you can provide both anonymous and signed up user with the same treatment.
206
-
207
- `bucketing_key` may be `nil` in that case `matching_key` would be used as a key, so calling
208
- ```ruby
209
- split_client.get_treatment(
210
- { matching_key: 'user_id' },
211
- 'feature_name',
212
- attr: 'val'
213
- )
214
- ```
215
- Is exactly the same as calling
216
- ```ruby
217
- split_client.get_treatment('user_id' ,'feature_name', attr: 'val')
218
- ```
219
- `bucketing_key` must not be nil
220
-
221
- Also you can use the split manager:
222
-
223
- ```ruby
224
- split_manager = SplitIoClient::SplitFactory.new('your_api_key', options).manager
225
- ```
226
-
227
- With the manager you can get a list of your splits by doing:
228
-
229
- ```ruby
230
- manager.splits
231
- ```
232
-
233
- And you should get something like this:
234
-
235
- ```ruby
236
- [
237
- {
238
- name: 'some_feature',
239
- traffic_type_name: nil,
240
- killed: false,
241
- treatments: nil,
242
- change_number: 1469134003507
243
- },
244
- {
245
- name: 'another_feature',
246
- traffic_type_name: nil,
247
- killed: false,
248
- treatments: nil,
249
- change_number: 1469134003414
250
- },
251
- {
252
- name: 'even_more_features',
253
- traffic_type_name: nil,
254
- killed: false,
255
- treatments: nil,
256
- change_number: 1469133991063
257
- },
258
- {
259
- name: 'yet_another_feature',
260
- traffic_type_name: nil,
261
- killed: false,
262
- treatments: nil,
263
- change_number: 1469133757521
264
- }
265
- ]
266
- ```
267
-
268
- ### SDK Modes
269
-
270
- By default SDK would run alongside with your application and will be run in `standalone` mode, which includes two modes:
271
- - `producer` - storing information from the Splits API in the chosen cache
272
- - `consumer` - retrieving data from the cache and providing `get_treatment` interface
273
-
274
- As you might think, you can choose between these 3 modes by providing `mode` option in the config.
275
-
276
- #### Producer mode
277
-
278
- If you have, say, one Redis cache which is used by several Split SDKs at once, e.g.: Python and Ruby, you want to have only one of them to write data to Redis, so it would remain consistent. That's why we have producer mode.
279
-
280
- SDK can be ran in `producer` mode both in the scope of the application (e.g. as a part of the Rails app), and as a separate process. Let's see what steps are needed to run it as a separate process:
281
-
282
- - You need to create a config file with .yml extension. All options specified in the above example section are valid, but you should write them in the YAML format, like this:
283
-
284
- ```yaml
285
- ---
286
- :api_key: 'SECRET_API_KEY'
287
- :connection_timeout: 10
288
- :read_timeout: 5
289
- :features_refresh_rate: 120
290
- :segments_refresh_rate: 120
291
- :metrics_refresh_rate: 360
292
- :impressions_refresh_rate: 360
293
- :block_until_ready: 5
294
- :cache_adapter: :redis
295
- :mode: :producer
296
- :redis_url: 'redis://127.0.0.1:6379/0'
297
- ```
298
-
299
- - Install binstubs
300
- ```ruby
301
- bundle binstubs splitclient-rb
302
- ```
303
-
304
- - Run the executable provided by the SDK:
305
- ```ruby
306
- bundle exec bin/splitio -c ~/path/to/config/file.yml
307
- ```
308
-
309
- That's it!
310
-
311
- ## Development
312
-
313
- After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
314
-
315
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
316
-
317
- ## Coverage
318
-
319
- The gem uses rspec for unit testing. Under the default `/spec` folder you will find the files for the unit tests and the specs helper file ( spec_helper.rb ). If a new spec file with new unit tests is required you just simply need to create it under the spec folder and all its test will be executed on the next rspec execution.
320
-
321
- To run the suite of unit tests a rake task is provided. It's executed with the following command:
322
-
323
- ```bash
324
- $ rake spec
325
- ```
326
-
327
- Also, simplecov is used for coverage reporting. After the execution of the rake task it will create the `/coverage` folder with coverage reports in pretty HTML format.
328
- Right now, the code coverage of the gem is at about 95%.
329
-
330
-
331
- ## Contributing
332
-
333
- Bug reports and pull requests are welcome on GitHub at https://github.com/splitio/ruby-client.
334
-
335
- ## Gem version publish
336
-
337
- To build a new version of the gem, after you have finished the desired changes, documented the CHANGES.txt and the NEWS, as well as named it properly in the version.rb. This steps assume that all of your new cool features and fixes have been merged into development, and into master branches of the ruby-client repo. Once that is ready to go, you will have to run the build command to obtain a .gem file:
338
-
339
- ```bash
340
- gem build splitclient-rb.gemspec
341
- ```
342
-
343
- That will generate a splitclient-rb-x.x.x.gem file, with the corresponding version information on it.
344
- To publish this new version of the gem at rubygems.org you must run the following command:
345
-
346
- ```bash
347
- gem push splitclient-rb-x.x.x.gem
348
- ```
349
-
350
- A valid rubygems username and password will be required.
351
-
352
- After this action, the new splitclient-rb-x.x.x version is available for its use from any ruby app.
353
-
354
- So for instance in a rails app Gemfile, you could add the:
355
-
356
- ```ruby
357
- gem 'splitclient-rb', '~> x.x.x'
358
- ```
359
-
360
- line to have the latest version of the gem ready to be used.
361
-
362
- ## License
363
-
364
- The gem is available as open source under the terms of the [Apache License](http://www.apache.org/licenses/).
@@ -31,7 +31,7 @@ module SplitIoClient
31
31
  if fields.is_a? Array
32
32
  fields.each { |field| @map[key].delete(field) }
33
33
  else
34
- @map[key].delete(field)
34
+ @map[key].delete(fields)
35
35
  end
36
36
  end
37
37
 
@@ -97,9 +97,11 @@ module SplitIoClient
97
97
  end
98
98
 
99
99
  def union_sets(set_keys)
100
- set_keys.each_with_object([]) do |key, memo|
100
+ array = set_keys.each_with_object([]) do |key, memo|
101
101
  memo << get_set(key)
102
102
  end.flatten
103
+
104
+ Set.new(array)
103
105
  end
104
106
 
105
107
  # General
@@ -4,24 +4,32 @@ module SplitIoClient
4
4
  module MemoryAdapters
5
5
  # Memory adapter implementation, which stores everything inside queue
6
6
  class QueueAdapter
7
- def initialize(size)
8
- @size = size
7
+ def initialize(max_size)
8
+ @max_size = max_size
9
9
  @queue = Queue.new
10
+ @current_size = Concurrent::AtomicFixnum.new(0)
10
11
  end
11
12
 
12
13
  # Adds data to queue in non-blocking mode
13
14
  def add_to_queue(data)
15
+ fail ThreadError if @current_size.value >= @max_size
16
+
14
17
  @queue.push(data)
18
+
19
+ @current_size.increment
15
20
  end
16
21
 
17
22
  # Get all items from the queue
18
23
  def clear
19
24
  items = []
20
25
 
21
- loop { items << @queue.pop(true) }
26
+ loop do
27
+ items << @queue.pop(true)
28
+
29
+ @current_size.decrement
30
+ end
22
31
 
23
32
  rescue ThreadError
24
- # Last queue item reached
25
33
  items
26
34
  end
27
35
  end