unleash 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/.travis.yml +5 -2
- data/README.md +37 -8
- data/TODO.md +5 -5
- data/lib/unleash/client.rb +18 -9
- data/lib/unleash/configuration.rb +5 -1
- data/lib/unleash/context.rb +26 -5
- data/lib/unleash/feature_toggle.rb +7 -5
- data/lib/unleash/scheduled_executor.rb +5 -1
- data/lib/unleash/strategy/gradual_rollout_sessionid.rb +1 -0
- data/lib/unleash/strategy/gradual_rollout_userid.rb +1 -0
- data/lib/unleash/version.rb +1 -1
- data/unleash-client.gemspec +4 -3
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7d8661e45cf753ab1c4ffdda0c4445657237cf0dafb26c1f701e258a3fe8c28f
|
4
|
+
data.tar.gz: 440ddb7d149983453cbda346264e12510fb97a3372ac99bcb5e5e8d60e25df7d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d913c18a4dc0894b19a6281dfb6112891bcb296725afd75aa84172fc7849b36c87962f55151094820d0951c0ea5ec2dd4c8e0e9ce946cc99e2747c9b41e94472
|
7
|
+
data.tar.gz: bcd865ead7231ea7dbc24b3318498ccbddaab5a7032375c8d25f603952b094141126ebae8e0cf668e74d7ba9e6c73be27f083175211529714967e941d0744521
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -1,9 +1,12 @@
|
|
1
1
|
sudo: false
|
2
2
|
language: ruby
|
3
3
|
rvm:
|
4
|
-
- 2.2
|
5
4
|
- 2.3
|
6
5
|
- 2.4
|
7
6
|
- 2.5
|
7
|
+
- 2.6
|
8
8
|
- jruby
|
9
|
-
before_install:
|
9
|
+
before_install:
|
10
|
+
- gem install bundler -v 2.0.1
|
11
|
+
# install client spec from official repository:
|
12
|
+
- git clone --depth 5 https://github.com/Unleash/client-specification.git client-specification
|
data/README.md
CHANGED
@@ -12,7 +12,7 @@ Leverage the [Unleash Server](https://github.com/Unleash/unleash) for powerful f
|
|
12
12
|
Add this line to your application's Gemfile:
|
13
13
|
|
14
14
|
```ruby
|
15
|
-
gem 'unleash', '~> 0.1.
|
15
|
+
gem 'unleash', '~> 0.1.5'
|
16
16
|
```
|
17
17
|
|
18
18
|
And then execute:
|
@@ -25,16 +25,15 @@ Or install it yourself as:
|
|
25
25
|
|
26
26
|
## Configure
|
27
27
|
|
28
|
-
It is **required** to configure the `url` of the unleash server. Please substitute the sample `'http://unleash.herokuapp.com/api'` for the url of your own instance.
|
28
|
+
It is **required** to configure the `url` of the unleash server and `app_name` with the name of the runninng application. Please substitute the sample `'http://unleash.herokuapp.com/api'` for the url of your own instance.
|
29
29
|
|
30
|
-
It is **highly recommended** to configure `
|
30
|
+
It is **highly recommended** to configure the `instance_id` parameter as well.
|
31
31
|
|
32
|
-
For other options please see `lib/unleash/configuration.rb`.
|
33
32
|
|
34
33
|
```ruby
|
35
34
|
Unleash.configure do |config|
|
36
|
-
config.url
|
37
|
-
config.app_name
|
35
|
+
config.url = 'http://unleash.herokuapp.com/api'
|
36
|
+
config.app_name = 'my_ruby_app'
|
38
37
|
end
|
39
38
|
```
|
40
39
|
|
@@ -44,6 +43,27 @@ or instantiate the client with the valid configuration:
|
|
44
43
|
UNLEASH = Unleash::Client.new(url: 'http://unleash.herokuapp.com/api', app_name: 'my_ruby_app')
|
45
44
|
```
|
46
45
|
|
46
|
+
#### List of Arguments
|
47
|
+
|
48
|
+
Argument | Description | Required? | Type | Default Value|
|
49
|
+
---------|-------------|-----------|-------|---------------|
|
50
|
+
`url` | Unleash server URL. | Y | String | N/A |
|
51
|
+
`app_name` | Name of your program. | Y | String | N/A |
|
52
|
+
`instance_id` | Identifier for the running instance of program. Important so you can trace back to where metrics are being collected from. **Highly recommended be be set.** | N | String | random UUID |
|
53
|
+
`refresh_interval` | How often the unleash client should check with the server for configuration changes. | N | Integer | 15 |
|
54
|
+
`metrics_interval` | How often the unleash client should send metrics to server. | N | Integer | 10 |
|
55
|
+
`disable_client` | Disables all communication with the Unleash server. If set, `is_enabled?` will always answer with the `default_value` and configuration validation is skipped. Defeats the entire purpose of using unleash, but can be useful in when running tests. | N | Boolean | F |
|
56
|
+
`disable_metrics` | Disables sending metrics to Unleash server. | N | Boolean | F |
|
57
|
+
`custom_http_headers` | Custom headers to send to Unleash. | N | Hash | {} |
|
58
|
+
`timeout` | How long to wait for the connection to be established or wait in reading state (open_timeout/read_timeout) | N | Integer | 30 |
|
59
|
+
`retry_limit` | How many consecutive failures in connecting to the Unleash server are allowed before giving up. | N | Integer | 1 |
|
60
|
+
`backup_file` | Filename to store the last known state from the Unleash server. Best to not change this from the default. | N | `Dir.tmpdir + "/unleash-#{app_name}-repo.json` |
|
61
|
+
`logger` | Specify a custom `Logger` class to handle logs from the client. | N | `Logger.new(STDOUT)` |
|
62
|
+
`log_level` | Change the log level for the `Logger` class. | N | `Logger::ERROR` |
|
63
|
+
|
64
|
+
For in a more in depth look, please see `lib/unleash/configuration.rb`.
|
65
|
+
|
66
|
+
|
47
67
|
## Usage in a plain Ruby Application
|
48
68
|
|
49
69
|
```ruby
|
@@ -74,6 +94,7 @@ Unleash.configure do |config|
|
|
74
94
|
config.url = 'http://unleash.herokuapp.com/api'
|
75
95
|
config.app_name = Rails.application.class.parent.to_s
|
76
96
|
# config.instance_id = "#{Socket.gethostname}"
|
97
|
+
config.logger = Rails.logger
|
77
98
|
end
|
78
99
|
|
79
100
|
UNLEASH = Unleash::Client.new
|
@@ -139,6 +160,14 @@ if Rails.configuration.unleash.is_enabled? "AwesomeFeature", @unleash_context
|
|
139
160
|
end
|
140
161
|
```
|
141
162
|
|
163
|
+
If the feature is not found in the server, it will by default return false. However you can override that by setting the default return value to `true`:
|
164
|
+
|
165
|
+
```ruby
|
166
|
+
if UNLEASH.is_enabled? "AwesomeFeature", @unleash_context, true
|
167
|
+
puts "AwesomeFeature is enabled by default"
|
168
|
+
end
|
169
|
+
```
|
170
|
+
|
142
171
|
## Local test client
|
143
172
|
|
144
173
|
```
|
@@ -155,7 +184,7 @@ This client comes with the all the required strategies out of the box:
|
|
155
184
|
* GradualRolloutSessionIdStrategy
|
156
185
|
* GradualRolloutUserIdStrategy
|
157
186
|
* RemoteAddressStrategy
|
158
|
-
*
|
187
|
+
* UnknownStrategy
|
159
188
|
* UserWithIdStrategy
|
160
189
|
|
161
190
|
|
@@ -165,7 +194,7 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
|
165
194
|
|
166
195
|
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).
|
167
196
|
|
168
|
-
See (TODO.md) for known limitations, and feature roadmap.
|
197
|
+
See [TODO.md](TODO.md) for known limitations, and feature roadmap.
|
169
198
|
|
170
199
|
|
171
200
|
## Contributing
|
data/TODO.md
CHANGED
@@ -6,13 +6,10 @@ The Ruby client should be pretty stable now. But no warranty is given, and some
|
|
6
6
|
|
7
7
|
Implement:
|
8
8
|
----------
|
9
|
-
*
|
9
|
+
* Document writing of custom strategies.
|
10
10
|
|
11
11
|
To test: (and write tests for)
|
12
12
|
--------
|
13
|
-
* Implement spec test for ruby client specs using https://github.com/Unleash/client-specification/blob/master/05-gradual-rollout-random-strategy.json (similar to the examples below) to ensure consistent client behaviour.
|
14
|
-
* java: https://github.com/Unleash/unleash-client-java/compare/master...integration-spec
|
15
|
-
* node: https://github.com/Unleash/unleash-client-node/compare/client-specification?expand=1
|
16
13
|
* MetricsReporter
|
17
14
|
* everything else :)
|
18
15
|
|
@@ -34,4 +31,7 @@ DONE:
|
|
34
31
|
* Switch hashing function to use murmurhash3 as per https://github.com/Unleash/unleash/issues/247
|
35
32
|
* Document usage with Rails
|
36
33
|
* Support for allowing custom strategies.
|
37
|
-
|
34
|
+
* Possibility for custom HTTP headers when interacting with unleash server.
|
35
|
+
* Implement spec test for ruby client specs using https://github.com/Unleash/client-specification/blob/master/05-gradual-rollout-random-strategy.json (similar to the examples below) to ensure consistent client behaviour.
|
36
|
+
* java: https://github.com/Unleash/unleash-client-java/compare/master...integration-spec
|
37
|
+
* node: https://github.com/Unleash/unleash-client-node/compare/client-specification?expand=1
|
data/lib/unleash/client.rb
CHANGED
@@ -15,22 +15,31 @@ module Unleash
|
|
15
15
|
Unleash.logger = Unleash.configuration.logger
|
16
16
|
Unleash.logger.level = Unleash.configuration.log_level
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
18
|
+
unless Unleash.configuration.disable_client
|
19
|
+
Unleash.toggle_fetcher = Unleash::ToggleFetcher.new
|
20
|
+
register
|
21
|
+
|
22
|
+
unless Unleash.configuration.disable_metrics
|
23
|
+
Unleash.toggle_metrics = Unleash::Metrics.new
|
24
|
+
Unleash.reporter = Unleash::MetricsReporter.new
|
25
|
+
scheduledExecutor = Unleash::ScheduledExecutor.new('MetricsReporter', Unleash.configuration.metrics_interval)
|
26
|
+
scheduledExecutor.run do
|
27
|
+
Unleash.reporter.send
|
28
|
+
end
|
27
29
|
end
|
30
|
+
else
|
31
|
+
Unleash.logger.warn "Unleash::Client is disabled! Will only return default results!"
|
28
32
|
end
|
29
33
|
end
|
30
34
|
|
31
35
|
def is_enabled?(feature, context = nil, default_value = false)
|
32
36
|
Unleash.logger.debug "Unleash::Client.is_enabled? feature: #{feature} with context #{context}"
|
33
37
|
|
38
|
+
if Unleash.configuration.disable_client
|
39
|
+
Unleash.logger.warn "unleash_client is disabled! Always returning #{default_value} for feature #{feature}!"
|
40
|
+
return default_value
|
41
|
+
end
|
42
|
+
|
34
43
|
toggle_as_hash = Unleash.toggles.select{ |toggle| toggle['name'] == feature }.first if Unleash.toggles
|
35
44
|
|
36
45
|
if toggle_as_hash.nil?
|
@@ -5,6 +5,7 @@ module Unleash
|
|
5
5
|
class Configuration
|
6
6
|
attr_accessor :url, :app_name, :instance_id,
|
7
7
|
:custom_http_headers,
|
8
|
+
:disable_client,
|
8
9
|
:disable_metrics, :timeout, :retry_limit,
|
9
10
|
:refresh_interval, :metrics_interval,
|
10
11
|
:backup_file, :logger, :log_level
|
@@ -19,6 +20,7 @@ module Unleash
|
|
19
20
|
else
|
20
21
|
raise ArgumentError, "custom_http_headers must be a hash."
|
21
22
|
end
|
23
|
+
self.disable_client = opts[:disable_client] || false
|
22
24
|
self.disable_metrics = opts[:disable_metrics] || false
|
23
25
|
self.refresh_interval = opts[:refresh_interval] || 15
|
24
26
|
self.metrics_interval = opts[:metrics_interval] || 10
|
@@ -28,7 +30,7 @@ module Unleash
|
|
28
30
|
self.backup_file = opts[:backup_file] || nil
|
29
31
|
|
30
32
|
self.logger = opts[:logger] || Logger.new(STDOUT)
|
31
|
-
self.log_level = opts[:log_level] || Logger::
|
33
|
+
self.log_level = opts[:log_level] || Logger::WARN
|
32
34
|
|
33
35
|
|
34
36
|
if opts[:logger].nil?
|
@@ -47,6 +49,8 @@ module Unleash
|
|
47
49
|
end
|
48
50
|
|
49
51
|
def validate!
|
52
|
+
return if self.disable_client
|
53
|
+
|
50
54
|
if self.app_name.nil? or self.url.nil?
|
51
55
|
raise ArgumentError, "URL and app_name are required parameters."
|
52
56
|
end
|
data/lib/unleash/context.rb
CHANGED
@@ -5,14 +5,35 @@ module Unleash
|
|
5
5
|
|
6
6
|
def initialize(params = {})
|
7
7
|
params_is_a_hash = params.is_a?(Hash)
|
8
|
-
self.user_id =
|
9
|
-
self.session_id =
|
10
|
-
self.remote_address =
|
11
|
-
self.properties =
|
8
|
+
self.user_id = fetch(params, 'userId')
|
9
|
+
self.session_id = fetch(params, 'sessionId')
|
10
|
+
self.remote_address = fetch(params, 'remoteAddress')
|
11
|
+
self.properties =
|
12
|
+
if params_is_a_hash && ( params.fetch(:properties, nil) || params.fetch('properties', nil) ).is_a?(Hash)
|
13
|
+
fetch(params, 'properties', {})
|
14
|
+
else
|
15
|
+
{}
|
16
|
+
end
|
12
17
|
end
|
13
18
|
|
14
19
|
def to_s
|
15
20
|
"<Context: user_id=#{self.user_id},session_id=#{self.session_id},remote_address=#{self.remote_address},properties=#{self.properties}>"
|
16
21
|
end
|
22
|
+
|
23
|
+
private
|
24
|
+
# Fetch key from hash. Try first with using camelCase, and if not found, try with snake case.
|
25
|
+
# This way we are are idiomatically compliant with ruby, but still giving priority to the same
|
26
|
+
# key names as in the other clients.
|
27
|
+
def fetch(params, camelcase_key, default_ret = '')
|
28
|
+
return default_ret unless params.is_a?(Hash)
|
29
|
+
return default_ret unless camelcase_key.is_a?(String) or camelcase_key.is_a?(Symbol)
|
30
|
+
|
31
|
+
params.fetch(camelcase_key, nil) || params.fetch(snake_sym(camelcase_key), nil) || default_ret
|
32
|
+
end
|
33
|
+
|
34
|
+
# transform CamelCase to snake_case and make it a sym, if it is a string
|
35
|
+
def snake_sym(key)
|
36
|
+
key.is_a?(String) ? key.gsub(/(.)([A-Z])/,'\1_\2').downcase.to_sym : key
|
37
|
+
end
|
17
38
|
end
|
18
|
-
end
|
39
|
+
end
|
@@ -5,10 +5,12 @@ module Unleash
|
|
5
5
|
attr_accessor :name, :enabled, :strategies, :choices, :choices_lock
|
6
6
|
|
7
7
|
def initialize(params={})
|
8
|
-
|
9
|
-
self.enabled = params['enabled'] || false
|
8
|
+
params = {} if params.nil?
|
10
9
|
|
11
|
-
self.
|
10
|
+
self.name = params.fetch('name', nil)
|
11
|
+
self.enabled = params.fetch('enabled', false)
|
12
|
+
|
13
|
+
self.strategies = params.fetch('strategies', [])
|
12
14
|
.select{|s| ( s.key?('name') && Unleash::STRATEGIES.key?(s['name'].to_sym) ) }
|
13
15
|
.map{|s| ActivationStrategy.new(s['name'], s['parameters'])} || []
|
14
16
|
|
@@ -26,12 +28,12 @@ module Unleash
|
|
26
28
|
context = nil
|
27
29
|
end
|
28
30
|
|
29
|
-
result = self.enabled && self.strategies.select{ |s|
|
31
|
+
result = self.enabled && ( self.strategies.select{ |s|
|
30
32
|
strategy = Unleash::STRATEGIES.fetch(s.name.to_sym, :unknown)
|
31
33
|
r = strategy.is_enabled?(s.params, context)
|
32
34
|
Unleash.logger.debug "Strategy #{s.name} returned #{r} with context: #{context}" #"for params #{s.params} "
|
33
35
|
r
|
34
|
-
}.any?
|
36
|
+
}.any? || self.strategies.empty? )
|
35
37
|
result ||= default_result
|
36
38
|
|
37
39
|
Unleash.logger.debug "FeatureToggle (enabled:#{self.enabled} default_result:#{default_result} and Strategies combined returned #{result})"
|
@@ -28,8 +28,12 @@ module Unleash
|
|
28
28
|
Unleash.logger.error "stacktrace: #{e.backtrace}"
|
29
29
|
end
|
30
30
|
|
31
|
-
|
31
|
+
if self.retry_count > self.max_exceptions
|
32
|
+
Unleash.logger.info "thread #{name} retry_count (#{self.retry_count}) exceeded max_exceptions (#{self.max_exceptions}). Stopping with retries."
|
33
|
+
break
|
34
|
+
end
|
32
35
|
end
|
36
|
+
Unleash.logger.info "thread #{name} ended"
|
33
37
|
end
|
34
38
|
end
|
35
39
|
end
|
@@ -11,6 +11,7 @@ module Unleash
|
|
11
11
|
def is_enabled?(params = {}, context)
|
12
12
|
return false unless params.is_a?(Hash) && params.has_key?('percentage')
|
13
13
|
return false unless context.class.name == 'Unleash::Context'
|
14
|
+
return false if context.session_id.empty?
|
14
15
|
|
15
16
|
percentage = Integer(params['percentage'] || 0)
|
16
17
|
(percentage > 0 && Util.get_normalized_number(context.session_id, params['groupId'] || "") <= percentage)
|
@@ -11,6 +11,7 @@ module Unleash
|
|
11
11
|
def is_enabled?(params = {}, context)
|
12
12
|
return false unless params.is_a?(Hash) && params.has_key?('percentage')
|
13
13
|
return false unless context.class.name == 'Unleash::Context'
|
14
|
+
return false if context.user_id.empty?
|
14
15
|
|
15
16
|
percentage = Integer(params['percentage'] || 0)
|
16
17
|
(percentage > 0 && Util.get_normalized_number(context.user_id, params['groupId'] || "") <= percentage)
|
data/lib/unleash/version.rb
CHANGED
data/unleash-client.gemspec
CHANGED
@@ -11,8 +11,9 @@ Gem::Specification.new do |spec|
|
|
11
11
|
spec.licenses = ["Apache-2.0"]
|
12
12
|
|
13
13
|
spec.summary = %q{Unleash feature toggle client.}
|
14
|
-
spec.description = %q{
|
15
|
-
over all feature toggles across all your applications and services.}
|
14
|
+
spec.description = %q{This is the ruby client for Unleash, a powerful feature toggle system
|
15
|
+
that gives you a great overview over all feature toggles across all your applications and services.}
|
16
|
+
|
16
17
|
spec.homepage = "https://github.com/unleash/unleash-client-ruby"
|
17
18
|
|
18
19
|
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
@@ -25,7 +26,7 @@ Gem::Specification.new do |spec|
|
|
25
26
|
|
26
27
|
spec.add_dependency "murmurhash3", "~> 0.1.6"
|
27
28
|
|
28
|
-
spec.add_development_dependency "bundler", "~>
|
29
|
+
spec.add_development_dependency "bundler", "~> 2.0"
|
29
30
|
spec.add_development_dependency "rake", "~> 10.0"
|
30
31
|
spec.add_development_dependency "rspec", "~> 3.0"
|
31
32
|
spec.add_development_dependency "webmock", "~> 3.0"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: unleash
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Renato Arruda
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-01-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: murmurhash3
|
@@ -30,14 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '2.0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '2.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rake
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -95,8 +95,8 @@ dependencies:
|
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
97
|
description: |-
|
98
|
-
|
99
|
-
over all feature toggles across all your applications and services.
|
98
|
+
This is the ruby client for Unleash, a powerful feature toggle system
|
99
|
+
that gives you a great overview over all feature toggles across all your applications and services.
|
100
100
|
email:
|
101
101
|
- rarruda@rarruda.org
|
102
102
|
executables: []
|