unleash 0.1.6 → 3.2.3

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: 99d6b4f0efb9cf53a2f86930e2e26594d2de8c72aee68ee20e1374f6ac1826cc
4
- data.tar.gz: ac9905dee38bb80b0f94595907e74856be1842149bfbfc54ee0ff8390bd9dcda
3
+ metadata.gz: 70d64956aa703576336ee95064ef909655a664159b571be5417ebf073f0de224
4
+ data.tar.gz: 36cff93bb8203971721e3eeace2d24d9db4075926d2c2609e5c6acd01179c2fd
5
5
  SHA512:
6
- metadata.gz: b0ce261b43d7325d3aac1ed62a60d7fdec14543d92e5da63f3e1e699ab6a79d5a529c9080f51dfaf641ce72e18518a61ac1f14395987b3e515503865ed1ef5bf
7
- data.tar.gz: 3b4cf6548b3c19be261f3794370a80868f0c07cec0988423aa1388f5a75349f880ef1b824652a2bd582814149c985f82e7e1b01772470e41fd119406272f3b42
6
+ metadata.gz: 7b8c366cc799582a672646c796858381189e9286149929bb5e37afc2404cce9ac140b0c004ba8a3a7f774b0d83c705c2c714932656121054ab920f58afa55b34
7
+ data.tar.gz: 6a4f8aa92aa80e17eb2477cc77a534dcbe44b2b63b3ff7c05867392252e808ec76750094adaf476c739c2641db1ef0f8a7c3729001fd7efe8ab209a255ebe968
data/.gitignore CHANGED
@@ -7,9 +7,10 @@
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
+ /vendor
10
11
 
11
12
  # rspec failure tracking
12
13
  .rspec_status
13
14
 
14
15
  # Clone of the client-specification
15
- /client-specification/
16
+ /client-specification/
data/.rubocop.yml CHANGED
@@ -1,16 +1,70 @@
1
+ # inherit_from: .rubocop_todo.yml
2
+
3
+ AllCops:
4
+ TargetRubyVersion: 2.5
5
+
1
6
  Naming/PredicateName:
2
- NameWhitelist:
7
+ AllowedMethods:
3
8
  - is_enabled?
4
9
 
5
- Metrics/LineLength:
10
+ Metrics/ClassLength:
6
11
  Max: 120
12
+ Layout/LineLength:
13
+ Max: 140
14
+ Metrics/MethodLength:
15
+ Max: 20
16
+ Metrics/BlockLength:
17
+ Max: 100
18
+ Exclude:
19
+ - 'spec/unleash/client_spec.rb'
20
+ - 'spec/unleash/feature_toggle_spec.rb'
7
21
 
8
- Style/RedundantSelf:
9
- Enabled: false
10
- Style/PreferredHashMethods:
22
+ Metrics/AbcSize:
23
+ Max: 25
24
+ Metrics/CyclomaticComplexity:
25
+ Max: 9
26
+ Metrics/PerceivedComplexity:
27
+ Max: 9
28
+
29
+ Style/Documentation:
11
30
  Enabled: false
31
+
12
32
  Style/StringLiterals:
13
33
  Enabled: false
34
+ Style/RedundantSelf:
35
+ Enabled: false
36
+
37
+ Style/SymbolArray:
38
+ EnforcedStyle: brackets
39
+ Style/WordArray:
40
+ EnforcedStyle: brackets
41
+ Style/PreferredHashMethods:
42
+ EnforcedStyle: verbose
43
+ Style/FrozenStringLiteralComment:
44
+ EnforcedStyle: never
45
+ Style/GuardClause:
46
+ MinBodyLength: 8
47
+
48
+ Style/HashEachMethods:
49
+ Enabled: true
50
+ Style/HashTransformKeys:
51
+ Enabled: true
52
+ Style/HashTransformValues:
53
+ Enabled: true
54
+
55
+ Style/IfInsideElse:
56
+ Exclude:
57
+ - 'bin/unleash-client'
58
+
59
+ Style/Next:
60
+ Exclude:
61
+ - 'lib/unleash/scheduled_executor.rb'
62
+
63
+ Layout/MultilineMethodCallIndentation:
64
+ EnforcedStyle: indented
14
65
 
15
66
  Layout/SpaceBeforeBlockBraces:
16
- Enabled: false
67
+ EnforcedStyle: no_space
68
+ Exclude:
69
+ - 'unleash-client.gemspec'
70
+ - 'spec/**/*.rb'
data/.travis.yml CHANGED
@@ -1,12 +1,15 @@
1
1
  sudo: false
2
2
  language: ruby
3
3
  rvm:
4
- - 2.3
5
- - 2.4
6
- - 2.5
7
- - 2.6
8
- - jruby
4
+ - jruby
5
+ - 3.0
6
+ - 2.7
7
+ - 2.6
8
+ - 2.5
9
9
  before_install:
10
- - gem install bundler -v 2.0.2
11
- # install client spec from official repository:
12
- - git clone --depth 5 https://github.com/Unleash/client-specification.git client-specification
10
+ - gem install bundler -v 2.1.4
11
+ - git clone --depth 5 --branch v3.3.0 https://github.com/Unleash/client-specification.git client-specification
12
+
13
+ notifications:
14
+ slack:
15
+ secure: x593zOjdl2yVB8uP54v8CmuCOat8GFHnK99NPvPHKvif5U7PGe0YOgYh4DC1+Jc9vfjn1ke+0++m+Gif4quowpeOaA/t45xpB494lyziXsBulYml245jRp9yzoUmIIt7KxHhv4rlo3Q1ztMJgh6a5yDCornKHW2bKTkLsvqVTwxBRatLOrt6K9O8FivO/NaqgcoXl7Rw0fOx/bsZtx2IAFueTCH19NoqW1mk9KFEZ96YqJSvuqmfDC0AO7siq03WKlB++nPlKe1QcrlPalCrcsSzrYNhYJ3akBTt/ZbE1v6YJv2L+zUqRnAPTY2H+qp8WejFQtdhIjfeJ/SWox0iWv/Wy/mTFfj+EhFO9Aq+xhMjJ1OOLtNAPoYJyatEVgJkILb6M26igTFcuI60xBbGNmh5ZYeyRdn5/xFb7G2zyJ2Swc3PvN1uLzMHfTF0R7WzGq4CRNGIOjrHTGncyB3IGAONOdJdM3iT9XKY6cdlRK0VkQjEsEMe0eNv2fxxLVSGna4sdJoTND6LhJ6qCfuS9DEDXwoRdLxAXxefycCh9VNp7gloMJx8IbHYxOW0BFZqc3hxNU9X2SwOj6j72DZMrdYDg2aPAW69HG0iMontQ37Di87JEW2F2Cpgb49+4twByrQNIx+st+DGNce1vpc0DN+KuJVdIcmha654lT7Ffe8=
data/README.md CHANGED
@@ -10,10 +10,10 @@ Leverage the [Unleash Server](https://github.com/Unleash/unleash) for powerful f
10
10
 
11
11
  ## Supported Ruby Interpreters
12
12
 
13
- * MRI 2.3
14
- * MRI 2.4
15
- * MRI 2.5
13
+ * MRI 3.0
14
+ * MRI 2.7
16
15
  * MRI 2.6
16
+ * MRI 2.5
17
17
  * jruby
18
18
 
19
19
  ## Installation
@@ -21,7 +21,7 @@ Leverage the [Unleash Server](https://github.com/Unleash/unleash) for powerful f
21
21
  Add this line to your application's Gemfile:
22
22
 
23
23
  ```ruby
24
- gem 'unleash', '~> 0.1.6'
24
+ gem 'unleash', '~> 3.2.3'
25
25
  ```
26
26
 
27
27
  And then execute:
@@ -66,7 +66,7 @@ Argument | Description | Required? | Type | Default Value|
66
66
  `disable_metrics` | Disables sending metrics to Unleash server. | N | Boolean | `false` |
67
67
  `custom_http_headers` | Custom headers to send to Unleash. | N | Hash | {} |
68
68
  `timeout` | How long to wait for the connection to be established or wait in reading state (open_timeout/read_timeout) | N | Integer | 30 |
69
- `retry_limit` | How many consecutive failures in connecting to the Unleash server are allowed before giving up. | N | Integer | 1 |
69
+ `retry_limit` | How many consecutive failures in connecting to the Unleash server are allowed before giving up. Use `Float::INFINITY` if you would like it to never give up. | N | Numeric | 5 |
70
70
  `backup_file` | Filename to store the last known state from the Unleash server. Best to not change this from the default. | N | String | `Dir.tmpdir + "/unleash-#{app_name}-repo.json` |
71
71
  `logger` | Specify a custom `Logger` class to handle logs for the Unleash client. | N | Class | `Logger.new(STDOUT)` |
72
72
  `log_level` | Change the log level for the `Logger` class. Constant from `Logger::Severity`. | N | Constant | `Logger::ERROR` |
@@ -242,8 +242,6 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
242
242
 
243
243
  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).
244
244
 
245
- See [TODO.md](TODO.md) for known limitations, and feature roadmap.
246
-
247
245
 
248
246
  ## Contributing
249
247
 
data/Rakefile CHANGED
@@ -3,4 +3,4 @@ require "rspec/core/rake_task"
3
3
 
4
4
  RSpec::Core::RakeTask.new(:spec)
5
5
 
6
- task :default => :spec
6
+ task default: :spec
data/bin/unleash-client CHANGED
@@ -12,7 +12,7 @@ options = {
12
12
  url: 'http://localhost:4242',
13
13
  demo: false,
14
14
  disable_metrics: true,
15
- sleep: 0.1,
15
+ sleep: 0.1
16
16
  }
17
17
 
18
18
  OptionParser.new do |opts|
@@ -57,17 +57,26 @@ raise 'feature_name is required. see --help for usage.' unless feature_name
57
57
 
58
58
  options[:verbose] = false if options[:quiet]
59
59
 
60
+ log_level = \
61
+ if options[:quiet]
62
+ Logger::ERROR
63
+ elsif options[:verbose]
64
+ Logger::DEBUG
65
+ else
66
+ Logger::WARN
67
+ end
68
+
60
69
  @unleash = Unleash::Client.new(
61
70
  url: options[:url],
62
71
  app_name: 'unleash-client-ruby-cli',
63
72
  disable_metrics: options[:metrics],
64
- log_level: log_level = options[:quiet] ? Logger::ERROR : (options[:verbose] ? Logger::DEBUG : Logger::WARN),
73
+ log_level: log_level
65
74
  )
66
75
 
67
- context_params = ARGV.map{ |e| e.split("=") }.map{ |k,v| [k.to_sym, v] }.to_h
68
- context_properties = context_params.reject{ |k,v| [:user_id, :session_id, :remote_address].include? k }
69
- context_params.select!{ |k,v| [:user_id, :session_id, :remote_address].include? k }
70
- context_params.merge!( properties: context_properties ) unless context_properties.nil?
76
+ context_params = ARGV.map{ |e| e.split("=") }.map{ |k, v| [k.to_sym, v] }.to_h
77
+ context_properties = context_params.reject{ |k, _v| [:user_id, :session_id, :remote_address].include? k }
78
+ context_params.select!{ |k, _v| [:user_id, :session_id, :remote_address].include? k }
79
+ context_params.merge!(properties: context_properties) unless context_properties.nil?
71
80
  unleash_context = Unleash::Context.new(context_params)
72
81
 
73
82
  if options[:verbose]
@@ -80,26 +89,21 @@ if options[:verbose]
80
89
  puts ""
81
90
  end
82
91
 
83
-
84
-
85
92
  if options[:demo]
86
93
  loop do
87
94
  enabled = @unleash.is_enabled?(feature_name, unleash_context)
88
95
  print enabled ? '.' : '|'
89
96
  sleep options[:sleep]
90
97
  end
98
+ elsif options[:variant]
99
+ variant = @unleash.get_variant(feature_name, unleash_context)
100
+ puts " For feature \'#{feature_name}\' got variant \'#{variant}\'"
91
101
  else
92
- if options[:variant]
93
- variant = @unleash.get_variant(feature_name, unleash_context)
94
- puts " For feature \'#{feature_name}\' got variant \'#{variant}\'"
102
+ if @unleash.is_enabled?(feature_name, unleash_context)
103
+ puts " \'#{feature_name}\' is enabled according to unleash"
95
104
  else
96
- if @unleash.is_enabled?(feature_name, unleash_context)
97
- puts " \'#{feature_name}\' is enabled according to unleash"
98
- else
99
- puts " \'#{feature_name}\' is disabled according to unleash"
100
- end
105
+ puts " \'#{feature_name}\' is disabled according to unleash"
101
106
  end
102
107
  end
103
108
 
104
-
105
109
  @unleash.shutdown
data/examples/simple.rb CHANGED
@@ -16,12 +16,14 @@ puts ">> START simple.rb"
16
16
 
17
17
  # or:
18
18
 
19
- @unleash = Unleash::Client.new( url: 'http://unleash.herokuapp.com/api', app_name: 'simple-test',
19
+ @unleash = Unleash::Client.new(
20
+ url: 'https://app.unleash-hosted.com/demo/api',
21
+ app_name: 'simple-test',
20
22
  instance_id: 'local-test-cli',
21
23
  refresh_interval: 2,
22
24
  metrics_interval: 2,
23
25
  retry_limit: 2,
24
- log_level: Logger::DEBUG,
26
+ custom_http_headers: {'Authorization': '943ca9171e2c884c545c5d82417a655fb77cec970cc3b78a8ff87f4406b495d0'},
25
27
  )
26
28
 
27
29
  # feature_name = "AwesomeFeature"
@@ -55,5 +57,3 @@ puts "> shutting down client..."
55
57
  @unleash.shutdown
56
58
 
57
59
  puts ">> END simple.rb"
58
-
59
-
@@ -1,16 +1,29 @@
1
1
  module Unleash
2
2
  class ActivationStrategy
3
- attr_accessor :name, :params
3
+ attr_accessor :name, :params, :constraints
4
4
 
5
- def initialize(name, params)
5
+ def initialize(name, params, constraints = [])
6
6
  self.name = name
7
7
 
8
8
  if params.is_a?(Hash)
9
9
  self.params = params
10
+ elsif params.nil?
11
+ self.params = {}
10
12
  else
11
- Unleash.logger.warn "Invalid params provided for ActivationStrategy #{params}"
13
+ Unleash.logger.warn "Invalid params provided for ActivationStrategy (params:#{params})"
12
14
  self.params = {}
13
15
  end
16
+
17
+ if constraints.is_a?(Array) && constraints.each{ |c| c.is_a?(Constraint) }
18
+ self.constraints = constraints
19
+ else
20
+ Unleash.logger.warn "Invalid constraints provided for ActivationStrategy (contraints: #{constraints})"
21
+ self.constraints = []
22
+ end
23
+ end
24
+
25
+ def matches_context?(context)
26
+ self.constraints.any?{ |c| c.matches_context? context }
14
27
  end
15
28
  end
16
29
  end
@@ -3,11 +3,11 @@ require 'unleash/toggle_fetcher'
3
3
  require 'unleash/metrics_reporter'
4
4
  require 'unleash/scheduled_executor'
5
5
  require 'unleash/feature_toggle'
6
+ require 'unleash/util/http'
6
7
  require 'logger'
7
8
  require 'time'
8
9
 
9
10
  module Unleash
10
-
11
11
  class Client
12
12
  attr_accessor :fetcher_scheduled_executor, :metrics_scheduled_executor
13
13
 
@@ -18,71 +18,56 @@ module Unleash
18
18
  Unleash.logger = Unleash.configuration.logger.clone
19
19
  Unleash.logger.level = Unleash.configuration.log_level
20
20
 
21
- unless Unleash.configuration.disable_client
22
- Unleash.toggle_fetcher = Unleash::ToggleFetcher.new
23
-
24
- register
25
-
26
- self.fetcher_scheduled_executor = Unleash::ScheduledExecutor.new('ToggleFetcher', Unleash.configuration.refresh_interval)
27
- self.fetcher_scheduled_executor.run do
28
- Unleash.toggle_fetcher.fetch
29
- end
30
-
31
- unless Unleash.configuration.disable_metrics
32
- Unleash.toggle_metrics = Unleash::Metrics.new
33
- Unleash.reporter = Unleash::MetricsReporter.new
34
- self.metrics_scheduled_executor = Unleash::ScheduledExecutor.new('MetricsReporter', Unleash.configuration.metrics_interval)
35
- self.metrics_scheduled_executor.run do
36
- Unleash.reporter.send
37
- end
38
- end
39
- else
21
+ if Unleash.configuration.disable_client
40
22
  Unleash.logger.warn "Unleash::Client is disabled! Will only return default results!"
23
+ return
41
24
  end
25
+
26
+ register
27
+ start_toggle_fetcher
28
+ start_metrics unless Unleash.configuration.disable_metrics
42
29
  end
43
30
 
44
31
  def is_enabled?(feature, context = nil, default_value = false)
45
- Unleash.logger.debug "Unleash::Client.is_enabled? feature: #{feature} with context #{context}"
32
+ Unleash.logger.debug "Unleash::Client.is_enabled? feature: #{feature} with context #{context}"
46
33
 
47
- if Unleash.configuration.disable_client
48
- Unleash.logger.warn "unleash_client is disabled! Always returning #{default_value} for feature #{feature}!"
49
- return default_value
50
- end
34
+ if Unleash.configuration.disable_client
35
+ Unleash.logger.warn "unleash_client is disabled! Always returning #{default_value} for feature #{feature}!"
36
+ return default_value
37
+ end
51
38
 
52
- toggle_as_hash = Unleash.toggles.select{ |toggle| toggle['name'] == feature }.first if Unleash.toggles
39
+ toggle_as_hash = Unleash&.toggles&.select{ |toggle| toggle['name'] == feature }&.first
53
40
 
54
- if toggle_as_hash.nil?
55
- Unleash.logger.debug "Unleash::Client.is_enabled? feature: #{feature} not found"
56
- return default_value
57
- end
41
+ if toggle_as_hash.nil?
42
+ Unleash.logger.debug "Unleash::Client.is_enabled? feature: #{feature} not found"
43
+ return default_value
44
+ end
58
45
 
59
- toggle = Unleash::FeatureToggle.new(toggle_as_hash)
60
- toggle_result = toggle.is_enabled?(context, default_value)
46
+ toggle = Unleash::FeatureToggle.new(toggle_as_hash)
61
47
 
62
- return toggle_result
48
+ toggle.is_enabled?(context, default_value)
63
49
  end
64
50
 
65
51
  # enabled? is a more ruby idiomatic method name than is_enabled?
66
- alias_method :enabled?, :is_enabled?
52
+ alias enabled? is_enabled?
67
53
 
68
54
  # execute a code block (passed as a parameter), if is_enabled? is true.
69
55
  def if_enabled(feature, context = nil, default_value = false, &blk)
70
- yield if is_enabled?(feature, context, default_value)
56
+ yield(blk) if is_enabled?(feature, context, default_value)
71
57
  end
72
58
 
73
-
74
- def get_variant(feature, context = nil, fallback_variant = false)
59
+ def get_variant(feature, context = nil, fallback_variant = nil)
75
60
  Unleash.logger.debug "Unleash::Client.get_variant for feature: #{feature} with context #{context}"
76
61
 
77
62
  if Unleash.configuration.disable_client
78
- Unleash.logger.warn "unleash_client is disabled! Always returning #{default_variant} for feature #{feature}!"
63
+ Unleash.logger.debug "unleash_client is disabled! Always returning #{default_variant} for feature #{feature}!"
79
64
  return fallback_variant || Unleash::FeatureToggle.disabled_variant
80
65
  end
81
66
 
82
- toggle_as_hash = Unleash.toggles.select{ |toggle| toggle['name'] == feature }.first if Unleash.toggles
67
+ toggle_as_hash = Unleash&.toggles&.select{ |toggle| toggle['name'] == feature }&.first
83
68
 
84
69
  if toggle_as_hash.nil?
85
- Unleash.logger.debug "Unleash::Client.is_enabled? feature: #{feature} not found"
70
+ Unleash.logger.debug "Unleash::Client.get_variant feature: #{feature} not found"
86
71
  return fallback_variant || Unleash::FeatureToggle.disabled_variant
87
72
  end
88
73
 
@@ -96,7 +81,7 @@ module Unleash
96
81
 
97
82
  # TODO: Add to README: name, payload, enabled (bool)
98
83
 
99
- return variant
84
+ variant
100
85
  end
101
86
 
102
87
  # safe shutdown: also flush metrics to server and toggles to disk
@@ -117,9 +102,10 @@ module Unleash
117
102
  end
118
103
 
119
104
  private
105
+
120
106
  def info
121
- return {
122
- 'appName': Unleash.configuration.app_name,
107
+ {
108
+ 'appName': Unleash.configuration.app_name,
123
109
  'instanceId': Unleash.configuration.instance_id,
124
110
  'sdkVersion': "unleash-client-ruby:" + Unleash::VERSION,
125
111
  'strategies': Unleash::STRATEGIES.keys,
@@ -128,28 +114,42 @@ module Unleash
128
114
  }
129
115
  end
130
116
 
131
- def register
132
- Unleash.logger.debug "register()"
133
-
134
- uri = URI(Unleash.configuration.client_register_url)
135
- http = Net::HTTP.new(uri.host, uri.port)
136
- http.use_ssl = true if uri.scheme == 'https'
137
- http.open_timeout = Unleash.configuration.timeout # in seconds
138
- http.read_timeout = Unleash.configuration.timeout # in seconds
117
+ def start_toggle_fetcher
118
+ Unleash.toggle_fetcher = Unleash::ToggleFetcher.new
119
+ self.fetcher_scheduled_executor = Unleash::ScheduledExecutor.new(
120
+ 'ToggleFetcher',
121
+ Unleash.configuration.refresh_interval,
122
+ Unleash.configuration.retry_limit
123
+ )
124
+ self.fetcher_scheduled_executor.run do
125
+ Unleash.toggle_fetcher.fetch
126
+ end
127
+ end
139
128
 
140
- headers = (Unleash.configuration.get_http_headers || {}).dup
141
- headers['Content-Type'] = 'application/json'
129
+ def start_metrics
130
+ Unleash.toggle_metrics = Unleash::Metrics.new
131
+ Unleash.reporter = Unleash::MetricsReporter.new
132
+ self.metrics_scheduled_executor = Unleash::ScheduledExecutor.new(
133
+ 'MetricsReporter',
134
+ Unleash.configuration.metrics_interval,
135
+ Unleash.configuration.retry_limit
136
+ )
137
+ self.metrics_scheduled_executor.run do
138
+ Unleash.reporter.send
139
+ end
140
+ end
142
141
 
143
- request = Net::HTTP::Post.new(uri.request_uri, headers)
144
- request.body = info.to_json
142
+ def register
143
+ Unleash.logger.debug "register()"
145
144
 
146
145
  # Send the request, if possible
147
146
  begin
148
- response = http.request(request)
149
- rescue Exception => e
147
+ response = Unleash::Util::Http.post(Unleash.configuration.client_register_url, info.to_json)
148
+ rescue StandardError => e
150
149
  Unleash.logger.error "unable to register client with unleash server due to exception #{e.class}:'#{e}'."
151
150
  Unleash.logger.error "stacktrace: #{e.backtrace}"
152
151
  end
152
+ Unleash.logger.debug "client registered: #{response}"
153
153
  end
154
154
  end
155
155
  end