unleash 0.1.4 → 0.1.5

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.
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: []