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.
- checksums.yaml +4 -4
- data/CHANGES.txt +2 -0
- data/Detailed-README.md +406 -0
- data/LICENSE +10 -199
- data/NEWS +1 -0
- data/README.md +30 -342
- data/lib/cache/adapters/memory_adapters/map_adapter.rb +4 -2
- data/lib/cache/adapters/memory_adapters/queue_adapter.rb +12 -4
- data/lib/cache/senders/impressions_formatter.rb +65 -0
- data/lib/cache/senders/impressions_sender.rb +59 -0
- data/lib/engine/api/client.rb +30 -8
- data/lib/engine/api/impressions.rb +34 -0
- data/lib/engine/api/segments.rb +1 -1
- data/lib/engine/api/splits.rb +1 -1
- data/lib/engine/parser/split_adapter.rb +7 -102
- data/lib/splitclient-rb.rb +3 -1
- data/lib/splitclient-rb/localhost_split_factory.rb +19 -1
- data/lib/splitclient-rb/split_config.rb +2 -0
- data/lib/splitclient-rb/split_factory.rb +35 -141
- data/lib/splitclient-rb/split_factory_builder.rb +9 -2
- data/lib/splitclient-rb/version.rb +1 -1
- metadata +8 -5
- data/lib/splitclient-rb/localhost_split_factory_builder.rb +0 -13
data/NEWS
CHANGED
data/README.md
CHANGED
@@ -1,364 +1,52 @@
|
|
1
1
|
# Split Ruby SDK
|
2
2
|
|
3
|
-
|
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
|
-
|
6
|
-
---
|
5
|
+
### Quick setup
|
7
6
|
|
8
|
-
|
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
|
-
|
9
|
+
### Commitment to Quality:
|
11
10
|
|
12
|
-
|
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
|
-
|
13
|
+
### About Split:
|
17
14
|
|
18
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
41
|
-
---
|
39
|
+
**Try Split for Free:**
|
42
40
|
|
43
|
-
|
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
|
-
|
46
|
-
```ruby
|
47
|
-
require 'splitclient-rb'
|
48
|
-
```
|
43
|
+
**Learn more about Split:**
|
49
44
|
|
50
|
-
|
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
|
-
|
57
|
-
```ruby
|
58
|
-
manager = factory.manager
|
59
|
-
```
|
47
|
+
**System Status:**
|
60
48
|
|
61
|
-
|
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
|
-
|
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(
|
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(
|
8
|
-
@
|
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
|
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
|