flipper 0.10.2 → 0.11.0.beta1
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 +4 -4
- data/.rubocop.yml +42 -0
- data/.rubocop_todo.yml +188 -0
- data/Changelog.md +10 -0
- data/Gemfile +6 -3
- data/README.md +4 -3
- data/Rakefile +13 -13
- data/docs/Adapters.md +2 -1
- data/docs/DockerCompose.md +6 -3
- data/docs/Gates.md +25 -3
- data/docs/Optimization.md +27 -5
- data/docs/api/README.md +73 -32
- data/docs/http/README.md +34 -0
- data/docs/read-only/README.md +22 -0
- data/examples/percentage_of_actors_group.rb +49 -0
- data/flipper.gemspec +15 -15
- data/lib/flipper.rb +2 -5
- data/lib/flipper/adapter.rb +10 -0
- data/lib/flipper/adapters/http.rb +147 -0
- data/lib/flipper/adapters/http/client.rb +83 -0
- data/lib/flipper/adapters/http/error.rb +14 -0
- data/lib/flipper/adapters/instrumented.rb +36 -36
- data/lib/flipper/adapters/memoizable.rb +2 -6
- data/lib/flipper/adapters/memory.rb +10 -9
- data/lib/flipper/adapters/operation_logger.rb +1 -1
- data/lib/flipper/adapters/pstore.rb +12 -11
- data/lib/flipper/adapters/read_only.rb +6 -6
- data/lib/flipper/dsl.rb +1 -3
- data/lib/flipper/feature.rb +11 -16
- data/lib/flipper/gate.rb +3 -3
- data/lib/flipper/gate_values.rb +6 -6
- data/lib/flipper/gates/group.rb +2 -2
- data/lib/flipper/gates/percentage_of_actors.rb +2 -2
- data/lib/flipper/instrumentation/log_subscriber.rb +2 -4
- data/lib/flipper/instrumentation/metriks.rb +1 -1
- data/lib/flipper/instrumentation/statsd.rb +1 -1
- data/lib/flipper/instrumentation/statsd_subscriber.rb +1 -3
- data/lib/flipper/instrumentation/subscriber.rb +11 -10
- data/lib/flipper/instrumenters/memory.rb +1 -5
- data/lib/flipper/instrumenters/noop.rb +1 -1
- data/lib/flipper/middleware/memoizer.rb +11 -27
- data/lib/flipper/middleware/setup_env.rb +44 -0
- data/lib/flipper/registry.rb +8 -10
- data/lib/flipper/spec/shared_adapter_specs.rb +45 -67
- data/lib/flipper/test/shared_adapter_test.rb +25 -31
- data/lib/flipper/typecast.rb +2 -2
- data/lib/flipper/types/actor.rb +2 -4
- data/lib/flipper/types/group.rb +1 -1
- data/lib/flipper/types/percentage.rb +2 -1
- data/lib/flipper/version.rb +1 -1
- data/spec/fixtures/feature.json +31 -0
- data/spec/flipper/adapters/http_spec.rb +148 -0
- data/spec/flipper/adapters/instrumented_spec.rb +20 -20
- data/spec/flipper/adapters/memoizable_spec.rb +59 -59
- data/spec/flipper/adapters/operation_logger_spec.rb +16 -16
- data/spec/flipper/adapters/pstore_spec.rb +6 -6
- data/spec/flipper/adapters/read_only_spec.rb +28 -34
- data/spec/flipper/dsl_spec.rb +73 -84
- data/spec/flipper/feature_check_context_spec.rb +27 -27
- data/spec/flipper/feature_spec.rb +186 -196
- data/spec/flipper/gate_spec.rb +11 -11
- data/spec/flipper/gate_values_spec.rb +46 -45
- data/spec/flipper/gates/actor_spec.rb +2 -2
- data/spec/flipper/gates/boolean_spec.rb +24 -23
- data/spec/flipper/gates/group_spec.rb +19 -19
- data/spec/flipper/gates/percentage_of_actors_spec.rb +10 -10
- data/spec/flipper/gates/percentage_of_time_spec.rb +2 -2
- data/spec/flipper/instrumentation/log_subscriber_spec.rb +20 -20
- data/spec/flipper/instrumentation/metriks_subscriber_spec.rb +20 -20
- data/spec/flipper/instrumentation/statsd_subscriber_spec.rb +11 -11
- data/spec/flipper/instrumenters/memory_spec.rb +5 -5
- data/spec/flipper/instrumenters/noop_spec.rb +6 -6
- data/spec/flipper/middleware/memoizer_spec.rb +83 -100
- data/spec/flipper/middleware/setup_env_spec.rb +76 -0
- data/spec/flipper/registry_spec.rb +35 -39
- data/spec/flipper/typecast_spec.rb +18 -18
- data/spec/flipper/types/actor_spec.rb +30 -29
- data/spec/flipper/types/boolean_spec.rb +8 -8
- data/spec/flipper/types/group_spec.rb +28 -28
- data/spec/flipper/types/percentage_spec.rb +14 -14
- data/spec/flipper_spec.rb +61 -54
- data/spec/helper.rb +26 -21
- data/spec/integration_spec.rb +121 -113
- data/spec/support/fake_udp_socket.rb +1 -1
- data/spec/support/spec_helpers.rb +32 -4
- data/test/adapters/pstore_test.rb +3 -3
- data/test/test_helper.rb +1 -1
- metadata +20 -5
@@ -5,22 +5,22 @@ require 'flipper/adapters/memory'
|
|
5
5
|
require 'flipper/instrumentation/log_subscriber'
|
6
6
|
|
7
7
|
RSpec.describe Flipper::Instrumentation::LogSubscriber do
|
8
|
-
let(:adapter)
|
8
|
+
let(:adapter) do
|
9
9
|
memory = Flipper::Adapters::Memory.new
|
10
|
-
Flipper::Adapters::Instrumented.new(memory, :
|
11
|
-
|
12
|
-
let(:flipper)
|
13
|
-
Flipper.new(adapter, :
|
14
|
-
|
10
|
+
Flipper::Adapters::Instrumented.new(memory, instrumenter: ActiveSupport::Notifications)
|
11
|
+
end
|
12
|
+
let(:flipper) do
|
13
|
+
Flipper.new(adapter, instrumenter: ActiveSupport::Notifications)
|
14
|
+
end
|
15
15
|
|
16
16
|
before do
|
17
|
-
Flipper.register(:admins)
|
17
|
+
Flipper.register(:admins) do |thing|
|
18
18
|
thing.respond_to?(:admin?) && thing.admin?
|
19
|
-
|
19
|
+
end
|
20
20
|
|
21
21
|
@io = StringIO.new
|
22
22
|
logger = Logger.new(@io)
|
23
|
-
logger.formatter = proc { |
|
23
|
+
logger.formatter = proc { |_severity, _datetime, _progname, msg| "#{msg}\n" }
|
24
24
|
described_class.logger = logger
|
25
25
|
end
|
26
26
|
|
@@ -30,25 +30,25 @@ RSpec.describe Flipper::Instrumentation::LogSubscriber do
|
|
30
30
|
|
31
31
|
let(:log) { @io.string }
|
32
32
|
|
33
|
-
context
|
33
|
+
context 'feature enabled checks' do
|
34
34
|
before do
|
35
35
|
clear_logs
|
36
36
|
flipper[:search].enabled?
|
37
37
|
end
|
38
38
|
|
39
|
-
it
|
39
|
+
it 'logs feature calls with result after operation' do
|
40
40
|
feature_line = find_line('Flipper feature(search) enabled? false')
|
41
41
|
expect(feature_line).to include('[ thing=nil ]')
|
42
42
|
end
|
43
43
|
|
44
|
-
it
|
44
|
+
it 'logs adapter calls' do
|
45
45
|
adapter_line = find_line('Flipper feature(search) adapter(memory) get')
|
46
46
|
expect(adapter_line).to include('[ result={')
|
47
47
|
expect(adapter_line).to include('} ]')
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
-
context
|
51
|
+
context 'feature enabled checks with a thing' do
|
52
52
|
let(:user) { Flipper::Types::Actor.new(Struct.new(:flipper_id).new('1')) }
|
53
53
|
|
54
54
|
before do
|
@@ -56,13 +56,13 @@ RSpec.describe Flipper::Instrumentation::LogSubscriber do
|
|
56
56
|
flipper[:search].enabled?(user)
|
57
57
|
end
|
58
58
|
|
59
|
-
it
|
59
|
+
it 'logs thing for feature' do
|
60
60
|
feature_line = find_line('Flipper feature(search) enabled?')
|
61
61
|
expect(feature_line).to include(user.inspect)
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
65
|
-
context
|
65
|
+
context 'changing feature enabled state' do
|
66
66
|
let(:user) { Flipper::Types::Actor.new(Struct.new(:flipper_id).new('1')) }
|
67
67
|
|
68
68
|
before do
|
@@ -70,24 +70,24 @@ RSpec.describe Flipper::Instrumentation::LogSubscriber do
|
|
70
70
|
flipper[:search].enable(user)
|
71
71
|
end
|
72
72
|
|
73
|
-
it
|
73
|
+
it 'logs feature calls with result in brackets' do
|
74
74
|
feature_line = find_line('Flipper feature(search) enable true')
|
75
75
|
expect(feature_line).to include("[ thing=#{user.inspect} gate_name=actor ]")
|
76
76
|
end
|
77
77
|
|
78
|
-
it
|
78
|
+
it 'logs adapter value' do
|
79
79
|
adapter_line = find_line('Flipper feature(search) adapter(memory) enable')
|
80
|
-
expect(adapter_line).to include(
|
80
|
+
expect(adapter_line).to include('[ result=')
|
81
81
|
end
|
82
82
|
end
|
83
83
|
|
84
|
-
context
|
84
|
+
context 'getting all the features from the adapter' do
|
85
85
|
before do
|
86
86
|
clear_logs
|
87
87
|
flipper.features
|
88
88
|
end
|
89
89
|
|
90
|
-
it
|
90
|
+
it 'logs adapter calls' do
|
91
91
|
adapter_line = find_line('Flipper adapter(memory) features')
|
92
92
|
expect(adapter_line).to include('[ result=')
|
93
93
|
end
|
@@ -3,13 +3,13 @@ require 'flipper/adapters/memory'
|
|
3
3
|
require 'flipper/instrumentation/metriks'
|
4
4
|
|
5
5
|
RSpec.describe Flipper::Instrumentation::MetriksSubscriber do
|
6
|
-
let(:adapter)
|
6
|
+
let(:adapter) do
|
7
7
|
memory = Flipper::Adapters::Memory.new
|
8
|
-
Flipper::Adapters::Instrumented.new(memory, :
|
9
|
-
|
10
|
-
let(:flipper)
|
11
|
-
Flipper.new(adapter, :
|
12
|
-
|
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
13
|
|
14
14
|
let(:user) { user = Struct.new(:flipper_id).new('1') }
|
15
15
|
|
@@ -17,36 +17,36 @@ RSpec.describe Flipper::Instrumentation::MetriksSubscriber do
|
|
17
17
|
Metriks::Registry.default.clear
|
18
18
|
end
|
19
19
|
|
20
|
-
context
|
21
|
-
it
|
20
|
+
context 'for enabled feature' do
|
21
|
+
it 'updates feature metrics when calls happen' do
|
22
22
|
flipper[:stats].enable(user)
|
23
|
-
expect(Metriks.timer(
|
23
|
+
expect(Metriks.timer('flipper.feature_operation.enable').count).to be(1)
|
24
24
|
|
25
25
|
flipper[:stats].enabled?(user)
|
26
|
-
expect(Metriks.timer(
|
27
|
-
expect(Metriks.meter(
|
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
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
-
context
|
32
|
-
it
|
31
|
+
context 'for disabled feature' do
|
32
|
+
it 'updates feature metrics when calls happen' do
|
33
33
|
flipper[:stats].disable(user)
|
34
|
-
expect(Metriks.timer(
|
34
|
+
expect(Metriks.timer('flipper.feature_operation.disable').count).to be(1)
|
35
35
|
|
36
36
|
flipper[:stats].enabled?(user)
|
37
|
-
expect(Metriks.timer(
|
38
|
-
expect(Metriks.meter(
|
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
39
|
end
|
40
40
|
end
|
41
41
|
|
42
|
-
it
|
42
|
+
it 'updates adapter metrics when calls happen' do
|
43
43
|
flipper[:stats].enable(user)
|
44
|
-
expect(Metriks.timer(
|
44
|
+
expect(Metriks.timer('flipper.adapter.memory.enable').count).to be(1)
|
45
45
|
|
46
46
|
flipper[:stats].enabled?(user)
|
47
|
-
expect(Metriks.timer(
|
47
|
+
expect(Metriks.timer('flipper.adapter.memory.get').count).to be(1)
|
48
48
|
|
49
49
|
flipper[:stats].disable(user)
|
50
|
-
expect(Metriks.timer(
|
50
|
+
expect(Metriks.timer('flipper.adapter.memory.disable').count).to be(1)
|
51
51
|
end
|
52
52
|
end
|
@@ -7,13 +7,13 @@ require 'statsd'
|
|
7
7
|
RSpec.describe Flipper::Instrumentation::StatsdSubscriber do
|
8
8
|
let(:statsd_client) { Statsd.new }
|
9
9
|
let(:socket) { FakeUDPSocket.new }
|
10
|
-
let(:adapter)
|
10
|
+
let(:adapter) do
|
11
11
|
memory = Flipper::Adapters::Memory.new
|
12
|
-
Flipper::Adapters::Instrumented.new(memory, :
|
13
|
-
|
14
|
-
let(:flipper)
|
15
|
-
Flipper.new(adapter, :
|
16
|
-
|
12
|
+
Flipper::Adapters::Instrumented.new(memory, instrumenter: ActiveSupport::Notifications)
|
13
|
+
end
|
14
|
+
let(:flipper) do
|
15
|
+
Flipper.new(adapter, instrumenter: ActiveSupport::Notifications)
|
16
|
+
end
|
17
17
|
|
18
18
|
let(:user) { user = Struct.new(:flipper_id).new('1') }
|
19
19
|
|
@@ -38,8 +38,8 @@ RSpec.describe Flipper::Instrumentation::StatsdSubscriber do
|
|
38
38
|
expect(result).not_to be_nil
|
39
39
|
end
|
40
40
|
|
41
|
-
context
|
42
|
-
it
|
41
|
+
context 'for enabled feature' do
|
42
|
+
it 'updates feature metrics when calls happen' do
|
43
43
|
flipper[:stats].enable(user)
|
44
44
|
assert_timer 'flipper.feature_operation.enable'
|
45
45
|
|
@@ -49,8 +49,8 @@ RSpec.describe Flipper::Instrumentation::StatsdSubscriber do
|
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
52
|
-
context
|
53
|
-
it
|
52
|
+
context 'for disabled feature' do
|
53
|
+
it 'updates feature metrics when calls happen' do
|
54
54
|
flipper[:stats].disable(user)
|
55
55
|
assert_timer 'flipper.feature_operation.disable'
|
56
56
|
|
@@ -60,7 +60,7 @@ RSpec.describe Flipper::Instrumentation::StatsdSubscriber do
|
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
63
|
-
it
|
63
|
+
it 'updates adapter metrics when calls happen' do
|
64
64
|
flipper[:stats].enable(user)
|
65
65
|
assert_timer 'flipper.adapter.memory.enable'
|
66
66
|
|
@@ -2,18 +2,18 @@ require 'helper'
|
|
2
2
|
require 'flipper/instrumenters/memory'
|
3
3
|
|
4
4
|
RSpec.describe Flipper::Instrumenters::Memory do
|
5
|
-
describe
|
6
|
-
it
|
5
|
+
describe '#initialize' do
|
6
|
+
it 'sets events to empty array' do
|
7
7
|
instrumenter = described_class.new
|
8
8
|
expect(instrumenter.events).to eq([])
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
12
|
-
describe
|
13
|
-
it
|
12
|
+
describe '#instrument' do
|
13
|
+
it 'adds to events' do
|
14
14
|
instrumenter = described_class.new
|
15
15
|
name = 'user.signup'
|
16
|
-
payload = {:
|
16
|
+
payload = { email: 'john@doe.com' }
|
17
17
|
block_result = :yielded
|
18
18
|
|
19
19
|
result = instrumenter.instrument(name, payload) { block_result }
|
@@ -2,19 +2,19 @@ require 'helper'
|
|
2
2
|
require 'flipper/instrumenters/noop'
|
3
3
|
|
4
4
|
RSpec.describe Flipper::Instrumenters::Noop do
|
5
|
-
describe
|
6
|
-
context
|
7
|
-
it
|
5
|
+
describe '.instrument' do
|
6
|
+
context 'with name' do
|
7
|
+
it 'yields block' do
|
8
8
|
yielded = false
|
9
9
|
described_class.instrument(:foo) { yielded = true }
|
10
10
|
expect(yielded).to eq(true)
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
-
context
|
15
|
-
it
|
14
|
+
context 'with name and payload' do
|
15
|
+
it 'yields block' do
|
16
16
|
yielded = false
|
17
|
-
described_class.instrument(:foo,
|
17
|
+
described_class.instrument(:foo, pay: :load) { yielded = true }
|
18
18
|
expect(yielded).to eq(true)
|
19
19
|
end
|
20
20
|
end
|
@@ -8,66 +8,71 @@ RSpec.describe Flipper::Middleware::Memoizer do
|
|
8
8
|
include Rack::Test::Methods
|
9
9
|
|
10
10
|
let(:memory_adapter) { Flipper::Adapters::Memory.new }
|
11
|
-
let(:adapter)
|
11
|
+
let(:adapter) do
|
12
12
|
Flipper::Adapters::OperationLogger.new(memory_adapter)
|
13
|
-
|
14
|
-
let(:flipper)
|
13
|
+
end
|
14
|
+
let(:flipper) { Flipper.new(adapter) }
|
15
|
+
let(:env) { { 'flipper' => flipper } }
|
15
16
|
|
16
17
|
after do
|
17
18
|
flipper.adapter.memoize = nil
|
18
19
|
end
|
19
20
|
|
20
|
-
RSpec.shared_examples_for
|
21
|
-
it
|
21
|
+
RSpec.shared_examples_for 'flipper middleware' do
|
22
|
+
it 'delegates' do
|
22
23
|
called = false
|
23
|
-
app = lambda
|
24
|
+
app = lambda do |_env|
|
24
25
|
called = true
|
25
26
|
[200, {}, nil]
|
26
|
-
|
27
|
-
middleware = described_class.new
|
28
|
-
middleware.call(
|
27
|
+
end
|
28
|
+
middleware = described_class.new(app)
|
29
|
+
middleware.call(env)
|
29
30
|
expect(called).to eq(true)
|
30
31
|
end
|
31
32
|
|
32
|
-
it
|
33
|
-
app =
|
34
|
-
middleware = described_class.new
|
35
|
-
body = middleware.call(
|
33
|
+
it 'disables local cache after body close' do
|
34
|
+
app = ->(_env) { [200, {}, []] }
|
35
|
+
middleware = described_class.new(app)
|
36
|
+
body = middleware.call(env).last
|
36
37
|
|
37
38
|
expect(flipper.adapter.memoizing?).to eq(true)
|
38
39
|
body.close
|
39
40
|
expect(flipper.adapter.memoizing?).to eq(false)
|
40
41
|
end
|
41
42
|
|
42
|
-
it
|
43
|
-
app =
|
44
|
-
middleware = described_class.new
|
45
|
-
body = middleware.call(
|
43
|
+
it 'clears local cache after body close' do
|
44
|
+
app = ->(_env) { [200, {}, []] }
|
45
|
+
middleware = described_class.new(app)
|
46
|
+
body = middleware.call(env).last
|
46
47
|
|
47
48
|
flipper.adapter.cache['hello'] = 'world'
|
48
49
|
body.close
|
49
50
|
expect(flipper.adapter.cache).to be_empty
|
50
51
|
end
|
51
52
|
|
52
|
-
it
|
53
|
+
it 'clears the local cache with a successful request' do
|
53
54
|
flipper.adapter.cache['hello'] = 'world'
|
54
|
-
get '/'
|
55
|
+
get '/', {}, 'flipper' => flipper
|
55
56
|
expect(flipper.adapter.cache).to be_empty
|
56
57
|
end
|
57
58
|
|
58
|
-
it
|
59
|
+
it 'clears the local cache even when the request raises an error' do
|
59
60
|
flipper.adapter.cache['hello'] = 'world'
|
60
|
-
|
61
|
+
begin
|
62
|
+
get '/fail', {}, 'flipper' => flipper
|
63
|
+
rescue
|
64
|
+
nil
|
65
|
+
end
|
61
66
|
expect(flipper.adapter.cache).to be_empty
|
62
67
|
end
|
63
68
|
|
64
|
-
it
|
69
|
+
it 'caches getting a feature for duration of request' do
|
65
70
|
flipper[:stats].enable
|
66
71
|
|
67
72
|
# clear the log of operations
|
68
73
|
adapter.reset
|
69
74
|
|
70
|
-
app = lambda
|
75
|
+
app = lambda do |_env|
|
71
76
|
flipper[:stats].enabled?
|
72
77
|
flipper[:stats].enabled?
|
73
78
|
flipper[:stats].enabled?
|
@@ -75,188 +80,166 @@ RSpec.describe Flipper::Middleware::Memoizer do
|
|
75
80
|
flipper[:stats].enabled?
|
76
81
|
flipper[:stats].enabled?
|
77
82
|
[200, {}, []]
|
78
|
-
|
83
|
+
end
|
79
84
|
|
80
|
-
middleware = described_class.new
|
81
|
-
middleware.call(
|
85
|
+
middleware = described_class.new(app)
|
86
|
+
middleware.call(env)
|
82
87
|
|
83
88
|
expect(adapter.count(:get)).to be(1)
|
84
89
|
end
|
85
90
|
end
|
86
91
|
|
87
|
-
context
|
88
|
-
let(:app)
|
92
|
+
context 'with preload_all' do
|
93
|
+
let(:app) do
|
89
94
|
# ensure scoped for builder block, annoying...
|
90
95
|
instance = flipper
|
91
96
|
middleware = described_class
|
92
97
|
|
93
98
|
Rack::Builder.new do
|
94
|
-
use middleware,
|
99
|
+
use middleware, preload_all: true
|
95
100
|
|
96
|
-
map
|
97
|
-
run
|
101
|
+
map '/' do
|
102
|
+
run ->(_env) { [200, {}, []] }
|
98
103
|
end
|
99
104
|
|
100
|
-
map
|
101
|
-
run
|
105
|
+
map '/fail' do
|
106
|
+
run ->(_env) { raise 'FAIL!' }
|
102
107
|
end
|
103
108
|
end.to_app
|
104
|
-
|
105
|
-
|
106
|
-
include_examples "flipper middleware"
|
107
|
-
end
|
108
|
-
|
109
|
-
context "with preload_all" do
|
110
|
-
let(:app) {
|
111
|
-
# ensure scoped for builder block, annoying...
|
112
|
-
instance = flipper
|
113
|
-
middleware = described_class
|
114
|
-
|
115
|
-
Rack::Builder.new do
|
116
|
-
use middleware, instance, preload_all: true
|
117
|
-
|
118
|
-
map "/" do
|
119
|
-
run lambda {|env| [200, {}, []] }
|
120
|
-
end
|
121
|
-
|
122
|
-
map "/fail" do
|
123
|
-
run lambda {|env| raise "FAIL!" }
|
124
|
-
end
|
125
|
-
end.to_app
|
126
|
-
}
|
109
|
+
end
|
127
110
|
|
128
|
-
include_examples
|
111
|
+
include_examples 'flipper middleware'
|
129
112
|
|
130
|
-
it
|
113
|
+
it 'eagerly caches known features for duration of request' do
|
131
114
|
flipper[:stats].enable
|
132
115
|
flipper[:shiny].enable
|
133
116
|
|
134
117
|
# clear the log of operations
|
135
118
|
adapter.reset
|
136
119
|
|
137
|
-
app = lambda
|
120
|
+
app = lambda do |_env|
|
138
121
|
flipper[:stats].enabled?
|
139
122
|
flipper[:stats].enabled?
|
140
123
|
flipper[:shiny].enabled?
|
141
124
|
flipper[:shiny].enabled?
|
142
125
|
[200, {}, []]
|
143
|
-
|
126
|
+
end
|
144
127
|
|
145
|
-
middleware = described_class.new
|
146
|
-
middleware.call(
|
128
|
+
middleware = described_class.new(app, preload_all: true)
|
129
|
+
middleware.call(env)
|
147
130
|
|
148
131
|
expect(adapter.count(:features)).to be(1)
|
149
132
|
expect(adapter.count(:get_multi)).to be(1)
|
150
133
|
expect(adapter.last(:get_multi).args).to eq([[flipper[:stats], flipper[:shiny]]])
|
151
134
|
end
|
152
135
|
|
153
|
-
it
|
136
|
+
it 'caches unknown features for duration of request' do
|
154
137
|
# clear the log of operations
|
155
138
|
adapter.reset
|
156
139
|
|
157
|
-
app = lambda
|
140
|
+
app = lambda do |_env|
|
158
141
|
flipper[:other].enabled?
|
159
142
|
flipper[:other].enabled?
|
160
143
|
[200, {}, []]
|
161
|
-
|
144
|
+
end
|
162
145
|
|
163
|
-
middleware = described_class.new
|
164
|
-
middleware.call(
|
146
|
+
middleware = described_class.new(app, preload_all: true)
|
147
|
+
middleware.call(env)
|
165
148
|
|
166
149
|
expect(adapter.count(:get)).to be(1)
|
167
150
|
expect(adapter.last(:get).args).to eq([flipper[:other]])
|
168
151
|
end
|
169
152
|
end
|
170
153
|
|
171
|
-
context
|
172
|
-
let(:app)
|
154
|
+
context 'with preload specific' do
|
155
|
+
let(:app) do
|
173
156
|
# ensure scoped for builder block, annoying...
|
174
157
|
instance = flipper
|
175
158
|
middleware = described_class
|
176
159
|
|
177
160
|
Rack::Builder.new do
|
178
|
-
use middleware,
|
161
|
+
use middleware, preload: %i(stats)
|
179
162
|
|
180
|
-
map
|
181
|
-
run
|
163
|
+
map '/' do
|
164
|
+
run ->(_env) { [200, {}, []] }
|
182
165
|
end
|
183
166
|
|
184
|
-
map
|
185
|
-
run
|
167
|
+
map '/fail' do
|
168
|
+
run ->(_env) { raise 'FAIL!' }
|
186
169
|
end
|
187
170
|
end.to_app
|
188
|
-
|
171
|
+
end
|
189
172
|
|
190
|
-
include_examples
|
173
|
+
include_examples 'flipper middleware'
|
191
174
|
|
192
|
-
it
|
175
|
+
it 'eagerly caches specified features for duration of request' do
|
193
176
|
# clear the log of operations
|
194
177
|
adapter.reset
|
195
178
|
|
196
|
-
app = lambda
|
179
|
+
app = lambda do |_env|
|
197
180
|
flipper[:stats].enabled?
|
198
181
|
flipper[:stats].enabled?
|
199
182
|
flipper[:shiny].enabled?
|
200
183
|
flipper[:shiny].enabled?
|
201
184
|
[200, {}, []]
|
202
|
-
|
185
|
+
end
|
203
186
|
|
204
|
-
middleware = described_class.new app,
|
205
|
-
middleware.call(
|
187
|
+
middleware = described_class.new app, preload: %i(stats)
|
188
|
+
middleware.call(env)
|
206
189
|
|
207
190
|
expect(adapter.count(:get_multi)).to be(1)
|
208
191
|
expect(adapter.last(:get_multi).args).to eq([[flipper[:stats]]])
|
209
192
|
end
|
210
193
|
|
211
|
-
it
|
194
|
+
it 'caches unknown features for duration of request' do
|
212
195
|
# clear the log of operations
|
213
196
|
adapter.reset
|
214
197
|
|
215
|
-
app = lambda
|
198
|
+
app = lambda do |_env|
|
216
199
|
flipper[:other].enabled?
|
217
200
|
flipper[:other].enabled?
|
218
201
|
[200, {}, []]
|
219
|
-
|
202
|
+
end
|
220
203
|
|
221
|
-
middleware = described_class.new app,
|
222
|
-
middleware.call(
|
204
|
+
middleware = described_class.new app, preload: %i(stats)
|
205
|
+
middleware.call(env)
|
223
206
|
|
224
207
|
expect(adapter.count(:get)).to be(1)
|
225
208
|
expect(adapter.last(:get).args).to eq([flipper[:other]])
|
226
209
|
end
|
227
210
|
end
|
228
211
|
|
229
|
-
context
|
230
|
-
it
|
212
|
+
context 'when an app raises an exception' do
|
213
|
+
it 'resets memoize' do
|
231
214
|
begin
|
232
|
-
app =
|
233
|
-
middleware = described_class.new
|
234
|
-
middleware.call(
|
215
|
+
app = ->(_env) { raise }
|
216
|
+
middleware = described_class.new(app)
|
217
|
+
middleware.call(env)
|
235
218
|
rescue RuntimeError
|
236
219
|
expect(flipper.adapter.memoizing?).to be(false)
|
237
220
|
end
|
238
221
|
end
|
239
222
|
end
|
240
223
|
|
241
|
-
context
|
242
|
-
let(:app)
|
224
|
+
context 'with flipper setup in env' do
|
225
|
+
let(:app) do
|
243
226
|
# ensure scoped for builder block, annoying...
|
244
227
|
instance = flipper
|
245
228
|
middleware = described_class
|
246
229
|
|
247
230
|
Rack::Builder.new do
|
248
|
-
use middleware
|
231
|
+
use middleware
|
249
232
|
|
250
|
-
map
|
251
|
-
run
|
233
|
+
map '/' do
|
234
|
+
run ->(_env) { [200, {}, []] }
|
252
235
|
end
|
253
236
|
|
254
|
-
map
|
255
|
-
run
|
237
|
+
map '/fail' do
|
238
|
+
run ->(_env) { raise 'FAIL!' }
|
256
239
|
end
|
257
240
|
end.to_app
|
258
|
-
|
241
|
+
end
|
259
242
|
|
260
|
-
include_examples
|
243
|
+
include_examples 'flipper middleware'
|
261
244
|
end
|
262
245
|
end
|