flipper 0.11.0.beta7 → 0.11.0.beta8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +1 -0
- data/Changelog.md +1 -1
- data/Gemfile +0 -1
- data/README.md +1 -1
- data/docs/Gates.md +22 -7
- data/docs/Optimization.md +15 -24
- data/docs/http/README.md +4 -4
- data/lib/flipper.rb +3 -1
- data/lib/flipper/adapters/http.rb +1 -1
- data/lib/flipper/adapters/http/client.rb +1 -1
- data/lib/flipper/middleware/memoizer.rb +9 -7
- data/lib/flipper/version.rb +1 -1
- data/spec/flipper/adapters/http_spec.rb +7 -7
- data/spec/flipper/middleware/memoizer_spec.rb +52 -0
- data/spec/flipper_spec.rb +17 -0
- metadata +2 -7
- data/flipper-cache-store.gemspec +0 -24
- data/lib/flipper/instrumentation/metriks.rb +0 -6
- data/lib/flipper/instrumentation/metriks_subscriber.rb +0 -20
- data/spec/flipper/instrumentation/metriks_subscriber_spec.rb +0 -52
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 690b416d2f41272c1756a810581d20f5382dd73a
|
4
|
+
data.tar.gz: 7db56f6d59863e7b896442b89a8caff91b1ed502
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 68d9eeede5def4ad36cb7ffae54fc3c99203548b0942b6e95dc0f968865e9990d234fae1634df5bf3268d7ca181d279766b1022cdd8b983e6b80137202b5dbc0
|
7
|
+
data.tar.gz: cd61f0435c5265ef1bf126161940f6d87ccbeed1c63b60070903e552983addf4a5599f9c09eaa70de468f2921e1cdb42c54c1d031201a4b53f1f311528d60353
|
data/.rubocop_todo.yml
CHANGED
data/Changelog.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
### Backwards Compatibility Breaks
|
4
4
|
|
5
|
-
*
|
5
|
+
* Set flipper from env for API and UI (https://github.com/jnunemaker/flipper/pull/223 and https://github.com/jnunemaker/flipper/pull/229). It is documented, but now the memoizing middleware requires that the SetupEnv middleware is used first.
|
6
6
|
* Drop support for Ruby 2.0 as it is end of lined (https://github.com/jnunemaker/flipper/commit/c2c81ed89938155ce91acb5173ac38580f630e3d).
|
7
7
|
* Allow unregistered groups (https://github.com/jnunemaker/flipper/pull/244). Only break in compatibility is that previously unregistered groups could not be enabled and now they can be.
|
8
8
|
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -77,7 +77,7 @@ Of course there are more [examples for you to peruse](examples/). You could also
|
|
77
77
|
|
78
78
|
* [Gates](docs/Gates.md) - Boolean, Groups, Actors, % of Actors, and % of Time
|
79
79
|
* [Adapters](docs/Adapters.md) - Mongo, Redis, Cassandra, Active Record...
|
80
|
-
* [Instrumentation](docs/Instrumentation.md) - ActiveSupport::Notifications
|
80
|
+
* [Instrumentation](docs/Instrumentation.md) - ActiveSupport::Notifications and Statsd
|
81
81
|
* [Optimization](docs/Optimization.md) - Memoization middleware and Cache adapters
|
82
82
|
* [Web Interface](docs/ui/README.md) - Point and click...
|
83
83
|
* [API](docs/api/README.md) - HTTP API interface
|
data/docs/Gates.md
CHANGED
@@ -15,23 +15,27 @@ flipper[:stats].enabled? # check
|
|
15
15
|
|
16
16
|
## 2. Group
|
17
17
|
|
18
|
-
Turn on feature based on value of block. Super flexible way to turn on a feature for multiple things (users, people, accounts, etc.)
|
18
|
+
Turn on feature based on the return value of block. Super flexible way to turn on a feature for multiple things (users, people, accounts, etc.) as long as the thing returns true when passed to the block.
|
19
19
|
|
20
20
|
```ruby
|
21
|
+
# this registers a group
|
21
22
|
Flipper.register(:admins) do |actor|
|
22
23
|
actor.respond_to?(:admin?) && actor.admin?
|
23
24
|
end
|
24
25
|
|
25
26
|
flipper = Flipper.new(adapter)
|
26
27
|
|
27
|
-
flipper[:stats].enable flipper.group(:admins) #
|
28
|
+
flipper[:stats].enable flipper.group(:admins) # This registers a stats feature and turns it on for admins (which is anything that returns true from the registered block).
|
28
29
|
flipper[:stats].disable flipper.group(:admins) # turn off the stats feature for admins
|
29
30
|
|
30
31
|
person = Person.find(params[:id])
|
31
32
|
flipper[:stats].enabled? person # check if enabled, returns true if person.admin? is true
|
32
33
|
|
33
|
-
# you can also use shortcut methods
|
34
|
+
# you can also use shortcut methods. This also registers a stats feature and turns it on for admins.
|
34
35
|
flipper.enable_group :stats, :admins
|
36
|
+
person = Person.find(params[:id])
|
37
|
+
flipper[:stats].enabled? person # same as above. check if enabled, returns true if person.admin? is true
|
38
|
+
|
35
39
|
flipper.disable_group :stats, :admins
|
36
40
|
flipper[:stats].enable_group :admins
|
37
41
|
flipper[:stats].disable_group :admins
|
@@ -50,7 +54,7 @@ end
|
|
50
54
|
flipper[:stats].enable flipper.group(:admins)
|
51
55
|
```
|
52
56
|
|
53
|
-
- The above enables the stats feature to any object that returns true from the
|
57
|
+
- The above enables the stats feature to any object that returns true from the `:admins` proc.
|
54
58
|
|
55
59
|
```
|
56
60
|
person = Person.find(params[:id])
|
@@ -61,6 +65,16 @@ When the `person` object is passed to the `enabled?` method, it is then passed i
|
|
61
65
|
|
62
66
|
There is no requirement that the thing yielded to the block be a user model or whatever. It can be anything you want, therefore it is a good idea to check that the thing passed into the group block actually responds to what you are trying to do in the `register` proc.
|
63
67
|
|
68
|
+
In your application code, you can do something like this now:
|
69
|
+
|
70
|
+
```
|
71
|
+
if flipper[:stats].enabled?(some_admin)
|
72
|
+
# do thing...
|
73
|
+
else
|
74
|
+
raise "Your are not authorized to view this page"
|
75
|
+
end
|
76
|
+
```
|
77
|
+
|
64
78
|
## 3. Individual Actor
|
65
79
|
|
66
80
|
Turn feature on for individual thing. Think enable feature for someone to test or for a buddy. The only requirement for an individual actor is that it must respond to `flipper_id`.
|
@@ -137,13 +151,14 @@ flipper = Flipper.new(adapter)
|
|
137
151
|
# get percentage of time instance set to 5
|
138
152
|
percentage = flipper.time(5)
|
139
153
|
|
140
|
-
# turn on
|
141
|
-
# could be on during one request and off the next
|
154
|
+
# Register a feature called logging and turn it on for 5 percent of the time.
|
155
|
+
# This could be on during one request and off the next
|
142
156
|
# could even be on first time in request and off second time
|
143
157
|
flipper[:logging].enable percentage
|
158
|
+
flipper[:logging].enabled? # this will return true 5% of the time.
|
144
159
|
|
145
160
|
# you can also use shortcut methods
|
146
|
-
flipper.enable_percentage_of_time :search, 5
|
161
|
+
flipper.enable_percentage_of_time :search, 5 # registers a feature called "enable_percentage_of_time" and enables it 5% of the time
|
147
162
|
flipper.disable_percentage_of_time :search # sets to 0
|
148
163
|
flipper[:search].enable_percentage_of_time 5
|
149
164
|
flipper[:search].disable_percentage_of_time # sets to 0
|
data/docs/Optimization.md
CHANGED
@@ -2,43 +2,34 @@
|
|
2
2
|
|
3
3
|
## Memoizing Middleware
|
4
4
|
|
5
|
-
One optimization that flipper provides is a memoizing middleware. The memoizing middleware ensures that you only make one adapter call per feature per request.
|
5
|
+
One optimization that flipper provides is a memoizing middleware. The memoizing middleware ensures that you only make one adapter call per feature per request. This means if you check the same feature over and over, it will only make one Mongo, Redis, or whatever call per feature for the length of the request.
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
You can use the middleware from a Rails initializer like so:
|
7
|
+
You can use the middleware like so for Rails:
|
10
8
|
|
11
9
|
```ruby
|
12
|
-
#
|
13
|
-
|
10
|
+
# setup default instance (perhaps in config/initializer/flipper.rb)
|
11
|
+
Flipper.configure do |config|
|
12
|
+
config.default do
|
13
|
+
Flipper.new(...)
|
14
|
+
end
|
15
|
+
end
|
14
16
|
|
15
|
-
|
17
|
+
# This assumes you setup a default flipper instance using configure.
|
16
18
|
require 'flipper/middleware/memoizer'
|
17
|
-
config.middleware.use Flipper::Middleware::SetupEnv, flipper
|
18
19
|
config.middleware.use Flipper::Middleware::Memoizer
|
19
20
|
```
|
20
21
|
|
21
|
-
|
22
|
+
**Note**: Be sure that the middleware is high enough up in your stack that all feature checks are wrapped.
|
22
23
|
|
23
|
-
|
24
|
-
# config/initializers/flipper.rb
|
25
|
-
module MyRailsApp
|
26
|
-
def self.flipper
|
27
|
-
@flipper ||= Flipper.new(...)
|
28
|
-
end
|
29
|
-
end
|
24
|
+
**Also Note**: If you haven't setup a default instance, you can pass the instance to `SetupEnv` as `Memoizer` uses whatever is setup in the `env`:
|
30
25
|
|
31
|
-
|
26
|
+
```ruby
|
32
27
|
require 'flipper/middleware/setup_env'
|
33
28
|
require 'flipper/middleware/memoizer'
|
34
|
-
config.middleware.use Flipper::Middleware::SetupEnv,
|
35
|
-
MyRailsApp.flipper
|
36
|
-
}
|
29
|
+
config.middleware.use Flipper::Middleware::SetupEnv, -> { Flipper.new(...) }
|
37
30
|
config.middleware.use Flipper::Middleware::Memoizer
|
38
31
|
```
|
39
32
|
|
40
|
-
**Note**: Be sure that the middleware is high enough up in your stack that all feature checks are wrapped.
|
41
|
-
|
42
33
|
### Options
|
43
34
|
|
44
35
|
The Memoizer middleware also supports a few options. Use either `preload` or `preload_all`, not both.
|
@@ -102,7 +93,7 @@ Rails applications can cache Flipper calls in any [ActiveSupport::Cache::Store](
|
|
102
93
|
|
103
94
|
Add this line to your application's Gemfile:
|
104
95
|
|
105
|
-
gem 'flipper-
|
96
|
+
gem 'flipper-cache_store'
|
106
97
|
|
107
98
|
And then execute:
|
108
99
|
|
@@ -110,7 +101,7 @@ And then execute:
|
|
110
101
|
|
111
102
|
Or install it yourself with:
|
112
103
|
|
113
|
-
$ gem install flipper-
|
104
|
+
$ gem install flipper-cache_store
|
114
105
|
|
115
106
|
Example using the CacheStore adapter with ActiveSupport's [MemoryStore](http://api.rubyonrails.org/classes/ActiveSupport/Cache/MemoryStore.html), Flipper's [Memory adapter](https://github.com/jnunemaker/flipper/blob/master/lib/flipper/adapters/memory.rb), and a TTL of 5 minutes.
|
116
107
|
|
data/docs/http/README.md
CHANGED
@@ -9,12 +9,12 @@ Initialize the HTTP adapter with a configuration Hash.
|
|
9
9
|
require 'flipper/adapters/http'
|
10
10
|
|
11
11
|
configuration = {
|
12
|
-
|
12
|
+
url: 'http://app.com/mount-point', # required
|
13
13
|
headers: { 'X-Custom-Header' => 'foo' },
|
14
14
|
basic_auth_username: 'user123',
|
15
15
|
basic_auth_password: 'password123'
|
16
|
-
read_timeout:
|
17
|
-
open_timeout:
|
16
|
+
read_timeout: 5,
|
17
|
+
open_timeout: 2,
|
18
18
|
}
|
19
19
|
|
20
20
|
adapter = Flipper::Adapters::Http.new(configuration)
|
@@ -22,7 +22,7 @@ flipper = Flipper.new(adapter)
|
|
22
22
|
```
|
23
23
|
|
24
24
|
**Required keys**:
|
25
|
-
*
|
25
|
+
* url: String url where [Flipper Api](https://github.com/jnunemaker/flipper/blob/master/docs/api/README.md) is mounted.
|
26
26
|
|
27
27
|
**Optional keys**:
|
28
28
|
*These will affect every request the adapter makes. For example, send basic auth credentials with every request.*
|
data/lib/flipper.rb
CHANGED
@@ -31,6 +31,8 @@ module Flipper
|
|
31
31
|
|
32
32
|
# Public: Sets Flipper::Configuration instance.
|
33
33
|
def configuration=(configuration)
|
34
|
+
# need to reset flipper instance if configuration changes
|
35
|
+
Thread.current[:flipper_instance] = nil
|
34
36
|
@configuration = configuration
|
35
37
|
end
|
36
38
|
|
@@ -55,7 +57,7 @@ module Flipper
|
|
55
57
|
:enable_percentage_of_time, :disable_percentage_of_time,
|
56
58
|
:time, :percentage_of_time,
|
57
59
|
:features, :feature, :[], :preload, :preload_all,
|
58
|
-
:add, :remove, :import
|
60
|
+
:adapter, :add, :remove, :import
|
59
61
|
|
60
62
|
# Public: Use this to register a group by name.
|
61
63
|
#
|
@@ -13,7 +13,7 @@ module Flipper
|
|
13
13
|
attr_reader :name
|
14
14
|
|
15
15
|
def initialize(options = {})
|
16
|
-
@client = Client.new(
|
16
|
+
@client = Client.new(url: options.fetch(:url),
|
17
17
|
headers: options[:headers],
|
18
18
|
basic_auth_username: options[:basic_auth_username],
|
19
19
|
basic_auth_password: options[:basic_auth_password],
|
@@ -15,7 +15,7 @@ module Flipper
|
|
15
15
|
HTTPS_SCHEME = "https".freeze
|
16
16
|
|
17
17
|
def initialize(options = {})
|
18
|
-
@uri = URI(options.fetch(:
|
18
|
+
@uri = URI(options.fetch(:url))
|
19
19
|
@headers = DEFAULT_HEADERS.merge(options[:headers] || {})
|
20
20
|
@basic_auth_username = options[:basic_auth_username]
|
21
21
|
@basic_auth_password = options[:basic_auth_password]
|
@@ -3,9 +3,10 @@ require 'rack/body_proxy'
|
|
3
3
|
module Flipper
|
4
4
|
module Middleware
|
5
5
|
class Memoizer
|
6
|
-
# Public: Initializes an instance of the Memoizer middleware.
|
7
|
-
#
|
8
|
-
#
|
6
|
+
# Public: Initializes an instance of the Memoizer middleware. Flipper must
|
7
|
+
# be configured with a default instance or the flipper instance must be
|
8
|
+
# setup in the env of the request. You can do this by using the
|
9
|
+
# Flipper::Middleware::SetupEnv middleware.
|
9
10
|
#
|
10
11
|
# app - The app this middleware is included in.
|
11
12
|
# opts - The Hash of options.
|
@@ -49,7 +50,8 @@ module Flipper
|
|
49
50
|
end
|
50
51
|
|
51
52
|
def memoized_call(env)
|
52
|
-
|
53
|
+
reset_on_body_close = false
|
54
|
+
flipper = env.fetch(@env_key) { Flipper }
|
53
55
|
original = flipper.adapter.memoizing?
|
54
56
|
flipper.adapter.memoize = true
|
55
57
|
|
@@ -63,10 +65,10 @@ module Flipper
|
|
63
65
|
response[2] = Rack::BodyProxy.new(response[2]) do
|
64
66
|
flipper.adapter.memoize = original
|
65
67
|
end
|
68
|
+
reset_on_body_close = true
|
66
69
|
response
|
67
|
-
|
68
|
-
flipper.adapter.memoize = original
|
69
|
-
raise
|
70
|
+
ensure
|
71
|
+
flipper.adapter.memoize = original if flipper && !reset_on_body_close
|
70
72
|
end
|
71
73
|
end
|
72
74
|
end
|
data/lib/flipper/version.rb
CHANGED
@@ -9,7 +9,7 @@ FLIPPER_SPEC_API_PORT = ENV.fetch('FLIPPER_SPEC_API_PORT', 9001).to_i
|
|
9
9
|
RSpec.describe Flipper::Adapters::Http do
|
10
10
|
context 'adapter' do
|
11
11
|
subject do
|
12
|
-
described_class.new(
|
12
|
+
described_class.new(url: "http://localhost:#{FLIPPER_SPEC_API_PORT}")
|
13
13
|
end
|
14
14
|
|
15
15
|
before :all do
|
@@ -66,7 +66,7 @@ RSpec.describe Flipper::Adapters::Http do
|
|
66
66
|
.with(headers: headers)
|
67
67
|
.to_return(status: 404, body: "", headers: {})
|
68
68
|
|
69
|
-
adapter = described_class.new(
|
69
|
+
adapter = described_class.new(url: 'http://app.com/flipper')
|
70
70
|
adapter.get(flipper[:feature_panel])
|
71
71
|
end
|
72
72
|
|
@@ -75,7 +75,7 @@ RSpec.describe Flipper::Adapters::Http do
|
|
75
75
|
stub_request(:get, "http://app.com/flipper/features/feature_panel")
|
76
76
|
.to_return(status: 503, body: "", headers: {})
|
77
77
|
|
78
|
-
adapter = described_class.new(
|
78
|
+
adapter = described_class.new(url: 'http://app.com/flipper')
|
79
79
|
expect do
|
80
80
|
adapter.get(flipper[:feature_panel])
|
81
81
|
end.to raise_error(Flipper::Adapters::Http::Error)
|
@@ -87,7 +87,7 @@ RSpec.describe Flipper::Adapters::Http do
|
|
87
87
|
stub_request(:get, "http://app.com/flipper/features?keys=feature_panel")
|
88
88
|
.to_return(status: 503, body: "", headers: {})
|
89
89
|
|
90
|
-
adapter = described_class.new(
|
90
|
+
adapter = described_class.new(url: 'http://app.com/flipper')
|
91
91
|
expect do
|
92
92
|
adapter.get_multi([flipper[:feature_panel]])
|
93
93
|
end.to raise_error(Flipper::Adapters::Http::Error)
|
@@ -99,7 +99,7 @@ RSpec.describe Flipper::Adapters::Http do
|
|
99
99
|
stub_request(:get, "http://app.com/flipper/features")
|
100
100
|
.to_return(status: 503, body: "", headers: {})
|
101
101
|
|
102
|
-
adapter = described_class.new(
|
102
|
+
adapter = described_class.new(url: 'http://app.com/flipper')
|
103
103
|
expect do
|
104
104
|
adapter.get_all
|
105
105
|
end.to raise_error(Flipper::Adapters::Http::Error)
|
@@ -111,7 +111,7 @@ RSpec.describe Flipper::Adapters::Http do
|
|
111
111
|
stub_request(:get, "http://app.com/flipper/features")
|
112
112
|
.to_return(status: 503, body: "", headers: {})
|
113
113
|
|
114
|
-
adapter = described_class.new(
|
114
|
+
adapter = described_class.new(url: 'http://app.com/flipper')
|
115
115
|
expect do
|
116
116
|
adapter.features
|
117
117
|
end.to raise_error(Flipper::Adapters::Http::Error)
|
@@ -122,7 +122,7 @@ RSpec.describe Flipper::Adapters::Http do
|
|
122
122
|
let(:debug_output) { object_double($stderr) }
|
123
123
|
let(:options) do
|
124
124
|
{
|
125
|
-
|
125
|
+
url: 'http://app.com/mount-point',
|
126
126
|
headers: { 'X-Custom-Header' => 'foo' },
|
127
127
|
basic_auth_username: 'username',
|
128
128
|
basic_auth_password: 'password',
|
@@ -254,6 +254,58 @@ RSpec.describe Flipper::Middleware::Memoizer do
|
|
254
254
|
include_examples 'flipper middleware'
|
255
255
|
end
|
256
256
|
|
257
|
+
context 'with Flipper setup in env' do
|
258
|
+
it 'caches getting a feature for duration of request' do
|
259
|
+
Flipper.configure do |config|
|
260
|
+
config.default do
|
261
|
+
memory = Flipper::Adapters::Memory.new
|
262
|
+
logged_adapter = Flipper::Adapters::OperationLogger.new(memory)
|
263
|
+
Flipper.new(logged_adapter)
|
264
|
+
end
|
265
|
+
end
|
266
|
+
Flipper.enable(:stats)
|
267
|
+
Flipper.adapter.reset # clear the log of operations
|
268
|
+
|
269
|
+
app = lambda do |_env|
|
270
|
+
Flipper.enabled?(:stats)
|
271
|
+
Flipper.enabled?(:stats)
|
272
|
+
Flipper.enabled?(:stats)
|
273
|
+
[200, {}, []]
|
274
|
+
end
|
275
|
+
|
276
|
+
middleware = described_class.new(app)
|
277
|
+
middleware.call('flipper' => Flipper)
|
278
|
+
|
279
|
+
expect(Flipper.adapter.count(:get)).to be(1)
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
context 'defaults to Flipper' do
|
284
|
+
it 'caches getting a feature for duration of request' do
|
285
|
+
Flipper.configure do |config|
|
286
|
+
config.default do
|
287
|
+
memory_adapter = Flipper::Adapters::Memory.new
|
288
|
+
logged_adapter = Flipper::Adapters::OperationLogger.new(memory_adapter)
|
289
|
+
Flipper.new(logged_adapter)
|
290
|
+
end
|
291
|
+
end
|
292
|
+
Flipper.enable(:stats)
|
293
|
+
Flipper.adapter.reset # clear the log of operations
|
294
|
+
|
295
|
+
app = lambda do |_env|
|
296
|
+
Flipper.enabled?(:stats)
|
297
|
+
Flipper.enabled?(:stats)
|
298
|
+
Flipper.enabled?(:stats)
|
299
|
+
[200, {}, []]
|
300
|
+
end
|
301
|
+
|
302
|
+
middleware = described_class.new(app)
|
303
|
+
middleware.call({})
|
304
|
+
|
305
|
+
expect(Flipper.adapter.count(:get)).to be(1)
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
257
309
|
context 'with preload_all and unless option' do
|
258
310
|
let(:app) do
|
259
311
|
# ensure scoped for builder block, annoying...
|
data/spec/flipper_spec.rb
CHANGED
@@ -39,6 +39,19 @@ RSpec.describe Flipper do
|
|
39
39
|
expect(described_class.instance).to be(instance)
|
40
40
|
expect(described_class.instance).to be(described_class.instance) # memoized
|
41
41
|
end
|
42
|
+
|
43
|
+
it 'is reset when configuration is changed' do
|
44
|
+
described_class.configure do |config|
|
45
|
+
config.default { described_class.new(Flipper::Adapters::Memory.new) }
|
46
|
+
end
|
47
|
+
original_instance = described_class.instance
|
48
|
+
|
49
|
+
new_config = Flipper::Configuration.new
|
50
|
+
new_config.default { described_class.new(Flipper::Adapters::Memory.new) }
|
51
|
+
described_class.configuration = new_config
|
52
|
+
|
53
|
+
expect(described_class.instance).not_to be(original_instance)
|
54
|
+
end
|
42
55
|
end
|
43
56
|
|
44
57
|
describe "delegation to instance" do
|
@@ -176,6 +189,10 @@ RSpec.describe Flipper do
|
|
176
189
|
described_class.import(other)
|
177
190
|
expect(described_class.enabled?(:search)).to be(true)
|
178
191
|
end
|
192
|
+
|
193
|
+
it 'delegates adapter to instance' do
|
194
|
+
expect(described_class.adapter).to eq(described_class.instance.adapter)
|
195
|
+
end
|
179
196
|
end
|
180
197
|
|
181
198
|
describe '.register' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flipper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.11.0.
|
4
|
+
version: 0.11.0.beta8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Nunemaker
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-10-28 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Feature flipper is the act of enabling/disabling features in your application,
|
14
14
|
ideally without re-deploying or changing anything in your code base. Flipper makes
|
@@ -52,7 +52,6 @@ files:
|
|
52
52
|
- examples/percentage_of_actors_enabled_check.rb
|
53
53
|
- examples/percentage_of_actors_group.rb
|
54
54
|
- examples/percentage_of_time.rb
|
55
|
-
- flipper-cache-store.gemspec
|
56
55
|
- flipper.gemspec
|
57
56
|
- lib/flipper.rb
|
58
57
|
- lib/flipper/actor.rb
|
@@ -79,8 +78,6 @@ files:
|
|
79
78
|
- lib/flipper/gates/percentage_of_actors.rb
|
80
79
|
- lib/flipper/gates/percentage_of_time.rb
|
81
80
|
- lib/flipper/instrumentation/log_subscriber.rb
|
82
|
-
- lib/flipper/instrumentation/metriks.rb
|
83
|
-
- lib/flipper/instrumentation/metriks_subscriber.rb
|
84
81
|
- lib/flipper/instrumentation/statsd.rb
|
85
82
|
- lib/flipper/instrumentation/statsd_subscriber.rb
|
86
83
|
- lib/flipper/instrumentation/subscriber.rb
|
@@ -122,7 +119,6 @@ files:
|
|
122
119
|
- spec/flipper/gates/percentage_of_actors_spec.rb
|
123
120
|
- spec/flipper/gates/percentage_of_time_spec.rb
|
124
121
|
- spec/flipper/instrumentation/log_subscriber_spec.rb
|
125
|
-
- spec/flipper/instrumentation/metriks_subscriber_spec.rb
|
126
122
|
- spec/flipper/instrumentation/statsd_subscriber_spec.rb
|
127
123
|
- spec/flipper/instrumenters/memory_spec.rb
|
128
124
|
- spec/flipper/instrumenters/noop_spec.rb
|
@@ -192,7 +188,6 @@ test_files:
|
|
192
188
|
- spec/flipper/gates/percentage_of_actors_spec.rb
|
193
189
|
- spec/flipper/gates/percentage_of_time_spec.rb
|
194
190
|
- spec/flipper/instrumentation/log_subscriber_spec.rb
|
195
|
-
- spec/flipper/instrumentation/metriks_subscriber_spec.rb
|
196
191
|
- spec/flipper/instrumentation/statsd_subscriber_spec.rb
|
197
192
|
- spec/flipper/instrumenters/memory_spec.rb
|
198
193
|
- spec/flipper/instrumenters/noop_spec.rb
|
data/flipper-cache-store.gemspec
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
require File.expand_path('../lib/flipper/version', __FILE__)
|
3
|
-
|
4
|
-
flipper_cache_store_files = lambda do |file|
|
5
|
-
file =~ /cache_store/
|
6
|
-
end
|
7
|
-
|
8
|
-
Gem::Specification.new do |gem|
|
9
|
-
gem.authors = ['John Nunemaker']
|
10
|
-
gem.email = ['nunemaker@gmail.com']
|
11
|
-
gem.summary = 'ActiveSupport::Cache::Store adapter for Flipper'
|
12
|
-
gem.description = 'ActiveSupport::Cache::Store adapter for Flipper'
|
13
|
-
gem.license = 'MIT'
|
14
|
-
gem.homepage = 'https://github.com/jnunemaker/flipper'
|
15
|
-
|
16
|
-
gem.files = `git ls-files`.split("\n").select(&flipper_cache_store_files) + ['lib/flipper/version.rb']
|
17
|
-
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n").select(&flipper_cache_store_files)
|
18
|
-
gem.name = 'flipper-cache-store'
|
19
|
-
gem.require_paths = ['lib']
|
20
|
-
gem.version = Flipper::VERSION
|
21
|
-
|
22
|
-
gem.add_dependency 'flipper', "~> #{Flipper::VERSION}"
|
23
|
-
gem.add_dependency 'activesupport', '>= 3.2', '< 6'
|
24
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
# Note: You should never need to require this file directly if you are using
|
2
|
-
# ActiveSupport::Notifications. Instead, you should require the metriks file
|
3
|
-
# that lives in the same directory as this file. The benefit is that it
|
4
|
-
# subscribes to the correct events and does everything for your.
|
5
|
-
require 'flipper/instrumentation/subscriber'
|
6
|
-
require 'metriks'
|
7
|
-
|
8
|
-
module Flipper
|
9
|
-
module Instrumentation
|
10
|
-
class MetriksSubscriber < Subscriber
|
11
|
-
def update_timer(metric)
|
12
|
-
Metriks.timer(metric).update(@duration)
|
13
|
-
end
|
14
|
-
|
15
|
-
def update_counter(metric)
|
16
|
-
Metriks.meter(metric).mark
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
@@ -1,52 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
require 'flipper/adapters/memory'
|
3
|
-
require 'flipper/instrumentation/metriks'
|
4
|
-
|
5
|
-
RSpec.describe Flipper::Instrumentation::MetriksSubscriber do
|
6
|
-
let(:adapter) do
|
7
|
-
memory = Flipper::Adapters::Memory.new
|
8
|
-
Flipper::Adapters::Instrumented.new(memory, instrumenter: ActiveSupport::Notifications)
|
9
|
-
end
|
10
|
-
let(:flipper) do
|
11
|
-
Flipper.new(adapter, instrumenter: ActiveSupport::Notifications)
|
12
|
-
end
|
13
|
-
|
14
|
-
let(:user) { user = Flipper::Actor.new('1') }
|
15
|
-
|
16
|
-
before do
|
17
|
-
Metriks::Registry.default.clear
|
18
|
-
end
|
19
|
-
|
20
|
-
context 'for enabled feature' do
|
21
|
-
it 'updates feature metrics when calls happen' do
|
22
|
-
flipper[:stats].enable(user)
|
23
|
-
expect(Metriks.timer('flipper.feature_operation.enable').count).to be(1)
|
24
|
-
|
25
|
-
flipper[:stats].enabled?(user)
|
26
|
-
expect(Metriks.timer('flipper.feature_operation.enabled').count).to be(1)
|
27
|
-
expect(Metriks.meter('flipper.feature.stats.enabled').count).to be(1)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
context 'for disabled feature' do
|
32
|
-
it 'updates feature metrics when calls happen' do
|
33
|
-
flipper[:stats].disable(user)
|
34
|
-
expect(Metriks.timer('flipper.feature_operation.disable').count).to be(1)
|
35
|
-
|
36
|
-
flipper[:stats].enabled?(user)
|
37
|
-
expect(Metriks.timer('flipper.feature_operation.enabled').count).to be(1)
|
38
|
-
expect(Metriks.meter('flipper.feature.stats.disabled').count).to be(1)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
it 'updates adapter metrics when calls happen' do
|
43
|
-
flipper[:stats].enable(user)
|
44
|
-
expect(Metriks.timer('flipper.adapter.memory.enable').count).to be(1)
|
45
|
-
|
46
|
-
flipper[:stats].enabled?(user)
|
47
|
-
expect(Metriks.timer('flipper.adapter.memory.get').count).to be(1)
|
48
|
-
|
49
|
-
flipper[:stats].disable(user)
|
50
|
-
expect(Metriks.timer('flipper.adapter.memory.disable').count).to be(1)
|
51
|
-
end
|
52
|
-
end
|