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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8abfb2ccb4ad16fa7842a94c42c715bc28e2b61e9e9ce4b7875a8ad92f47a696
4
- data.tar.gz: 59708b33a865480b75f7ffac3e153f32e7a2c19a0ad8338b0ef3872feaf57e8a
3
+ metadata.gz: 7d8661e45cf753ab1c4ffdda0c4445657237cf0dafb26c1f701e258a3fe8c28f
4
+ data.tar.gz: 440ddb7d149983453cbda346264e12510fb97a3372ac99bcb5e5e8d60e25df7d
5
5
  SHA512:
6
- metadata.gz: 47562d77f0847992c11e3b9f6a504bddc3eb057c62c9bd41f229bd9ddd73d9437f5736f9125790e5b6e9d10d2e6be7f383dee57a6bd33c13c42e58d8837931f7
7
- data.tar.gz: 3e081ffa547d95dca4e08030d21b7948ac5bf6d6af81fda91d37c2b328cd84a56f091ad3a83329bb5f86d5caf30e4befdb9d07eb3622e7439d2d5141df79718a
6
+ metadata.gz: d913c18a4dc0894b19a6281dfb6112891bcb296725afd75aa84172fc7849b36c87962f55151094820d0951c0ea5ec2dd4c8e0e9ce946cc99e2747c9b41e94472
7
+ data.tar.gz: bcd865ead7231ea7dbc24b3318498ccbddaab5a7032375c8d25f603952b094141126ebae8e0cf668e74d7ba9e6c73be27f083175211529714967e941d0744521
data/.gitignore CHANGED
@@ -10,3 +10,6 @@
10
10
 
11
11
  # rspec failure tracking
12
12
  .rspec_status
13
+
14
+ # Clone of the client-specification
15
+ /client-specification/
@@ -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: gem install bundler -v 1.14.6
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.4'
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 `app_name` and the `instance_id`.
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 = 'http://unleash.herokuapp.com/api'
37
- config.app_name = 'my_ruby_app'
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
- * UnknowndStrategy
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
- * Possibility for custom HTTP headers when interacting with unleash server.
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
@@ -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
- Unleash.toggle_fetcher = Unleash::ToggleFetcher.new
19
- register
20
-
21
- unless Unleash.configuration.disable_metrics
22
- Unleash.toggle_metrics = Unleash::Metrics.new
23
- Unleash.reporter = Unleash::MetricsReporter.new
24
- scheduledExecutor = Unleash::ScheduledExecutor.new('MetricsReporter', Unleash.configuration.metrics_interval)
25
- scheduledExecutor.run do
26
- Unleash.reporter.send
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::ERROR
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
@@ -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 = params_is_a_hash ? params.fetch(:user_id, '') : ''
9
- self.session_id = params_is_a_hash ? params.fetch(:session_id, '') : ''
10
- self.remote_address = params_is_a_hash ? params.fetch(:remote_address, '') : ''
11
- self.properties = params_is_a_hash && params[:properties].is_a?(Hash) ? params.fetch(: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
- self.name = params['name'] || nil
9
- self.enabled = params['enabled'] || false
8
+ params = {} if params.nil?
10
9
 
11
- self.strategies = params['strategies']
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
- break if self.retry_count > self.max_exceptions
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)
@@ -1,3 +1,3 @@
1
1
  module Unleash
2
- VERSION = "0.1.4"
2
+ VERSION = "0.1.5"
3
3
  end
@@ -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{Unleash is a feature toggle system, that gives you a great overview
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", "~> 1.14"
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
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: 2018-11-13 00:00:00.000000000 Z
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: '1.14'
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: '1.14'
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
- Unleash is a feature toggle system, that gives you a great overview
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: []