flipper 1.2.1 → 1.3.0.pre
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/.github/workflows/ci.yml +2 -1
- data/.github/workflows/examples.yml +1 -1
- data/Gemfile +0 -1
- data/README.md +1 -0
- data/lib/flipper/adapters/cache_base.rb +143 -0
- data/lib/flipper/adapters/operation_logger.rb +18 -88
- data/lib/flipper/adapters/read_only.rb +6 -39
- data/lib/flipper/adapters/strict.rb +5 -10
- data/lib/flipper/adapters/wrapper.rb +54 -0
- data/lib/flipper/cli.rb +38 -15
- data/lib/flipper/cloud/configuration.rb +2 -3
- data/lib/flipper/cloud/telemetry/instrumenter.rb +4 -8
- data/lib/flipper/cloud/telemetry.rb +10 -2
- data/lib/flipper/poller.rb +6 -5
- data/lib/flipper/serializers/gzip.rb +3 -5
- data/lib/flipper/serializers/json.rb +3 -5
- data/lib/flipper/spec/shared_adapter_specs.rb +17 -16
- data/lib/flipper/test/shared_adapter_test.rb +17 -17
- data/lib/flipper/test_help.rb +15 -10
- data/lib/flipper/typecast.rb +3 -3
- data/lib/flipper/version.rb +1 -1
- data/lib/flipper.rb +1 -0
- data/package-lock.json +41 -0
- data/package.json +10 -0
- data/spec/flipper/adapters/http_spec.rb +11 -2
- data/spec/flipper/cli_spec.rb +23 -23
- data/spec/flipper/cloud/configuration_spec.rb +29 -37
- data/spec/flipper/cloud/telemetry/backoff_policy_spec.rb +8 -9
- data/spec/flipper/cloud/telemetry_spec.rb +52 -0
- data/spec/flipper/cloud_spec.rb +6 -5
- data/spec/flipper/engine_spec.rb +39 -49
- data/spec/flipper/middleware/memoizer_spec.rb +7 -4
- data/spec/support/fail_on_output.rb +8 -0
- data/spec/support/spec_helpers.rb +2 -1
- data/test_rails/system/test_help_test.rb +8 -3
- metadata +9 -5
- data/spec/support/climate_control.rb +0 -7
@@ -160,8 +160,16 @@ module Flipper
|
|
160
160
|
# thus may have a telemetry-interval header for us to respect.
|
161
161
|
response ||= error.response if error && error.respond_to?(:response)
|
162
162
|
|
163
|
-
if response
|
164
|
-
|
163
|
+
if response
|
164
|
+
if Flipper::Typecast.to_boolean(response["telemetry-shutdown"])
|
165
|
+
debug "action=telemetry_shutdown message=The server has requested that telemetry be shut down."
|
166
|
+
stop
|
167
|
+
return
|
168
|
+
end
|
169
|
+
|
170
|
+
if interval = response["telemetry-interval"]
|
171
|
+
self.interval = interval.to_f
|
172
|
+
end
|
165
173
|
end
|
166
174
|
rescue => error
|
167
175
|
error "action=post_to_cloud error=#{error.inspect}"
|
data/lib/flipper/poller.rb
CHANGED
@@ -20,6 +20,8 @@ module Flipper
|
|
20
20
|
instances.each {|_, instance| instance.stop }.clear
|
21
21
|
end
|
22
22
|
|
23
|
+
MINIMUM_POLL_INTERVAL = 10
|
24
|
+
|
23
25
|
def initialize(options = {})
|
24
26
|
@thread = nil
|
25
27
|
@pid = Process.pid
|
@@ -30,9 +32,9 @@ module Flipper
|
|
30
32
|
@last_synced_at = Concurrent::AtomicFixnum.new(0)
|
31
33
|
@adapter = Adapters::Memory.new(nil, threadsafe: true)
|
32
34
|
|
33
|
-
if @interval <
|
34
|
-
warn "Flipper::Cloud poll interval must be greater than or equal to
|
35
|
-
@interval =
|
35
|
+
if @interval < MINIMUM_POLL_INTERVAL
|
36
|
+
warn "Flipper::Cloud poll interval must be greater than or equal to #{MINIMUM_POLL_INTERVAL} but was #{@interval}. Setting @interval to #{MINIMUM_POLL_INTERVAL}."
|
37
|
+
@interval = MINIMUM_POLL_INTERVAL
|
36
38
|
end
|
37
39
|
|
38
40
|
@start_automatically = options.fetch(:start_automatically, true)
|
@@ -64,8 +66,7 @@ module Flipper
|
|
64
66
|
# you can instrument these using poller.flipper
|
65
67
|
end
|
66
68
|
|
67
|
-
|
68
|
-
sleep sleep_interval if sleep_interval.positive?
|
69
|
+
sleep interval
|
69
70
|
end
|
70
71
|
end
|
71
72
|
|
@@ -3,10 +3,8 @@ require "stringio"
|
|
3
3
|
|
4
4
|
module Flipper
|
5
5
|
module Serializers
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
def serialize(source)
|
6
|
+
class Gzip
|
7
|
+
def self.serialize(source)
|
10
8
|
return if source.nil?
|
11
9
|
output = StringIO.new
|
12
10
|
gz = Zlib::GzipWriter.new(output)
|
@@ -15,7 +13,7 @@ module Flipper
|
|
15
13
|
output.string
|
16
14
|
end
|
17
15
|
|
18
|
-
def deserialize(source)
|
16
|
+
def self.deserialize(source)
|
19
17
|
return if source.nil?
|
20
18
|
Zlib::GzipReader.wrap(StringIO.new(source), &:read)
|
21
19
|
end
|
@@ -2,15 +2,13 @@ require "json"
|
|
2
2
|
|
3
3
|
module Flipper
|
4
4
|
module Serializers
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
def serialize(source)
|
5
|
+
class Json
|
6
|
+
def self.serialize(source)
|
9
7
|
return if source.nil?
|
10
8
|
JSON.generate(source)
|
11
9
|
end
|
12
10
|
|
13
|
-
def deserialize(source)
|
11
|
+
def self.deserialize(source)
|
14
12
|
return if source.nil?
|
15
13
|
JSON.parse(source)
|
16
14
|
end
|
@@ -108,19 +108,19 @@ RSpec.shared_examples_for 'a flipper adapter' do
|
|
108
108
|
actor22 = Flipper::Actor.new('22')
|
109
109
|
actor_asdf = Flipper::Actor.new('asdf')
|
110
110
|
|
111
|
-
expect(
|
112
|
-
expect(
|
111
|
+
expect(feature.enable(actor22)).to be(true)
|
112
|
+
expect(feature.enable(actor_asdf)).to be(true)
|
113
113
|
|
114
|
-
|
115
|
-
expect(
|
114
|
+
expect(feature).to be_enabled(actor22)
|
115
|
+
expect(feature).to be_enabled(actor_asdf)
|
116
116
|
|
117
|
-
expect(
|
118
|
-
|
119
|
-
expect(
|
117
|
+
expect(feature.disable(actor22)).to be(true)
|
118
|
+
expect(feature).not_to be_enabled(actor22)
|
119
|
+
expect(feature).to be_enabled(actor_asdf)
|
120
120
|
|
121
|
-
expect(
|
122
|
-
|
123
|
-
expect(
|
121
|
+
expect(feature.disable(actor_asdf)).to eq(true)
|
122
|
+
expect(feature).not_to be_enabled(actor22)
|
123
|
+
expect(feature).not_to be_enabled(actor_asdf)
|
124
124
|
end
|
125
125
|
|
126
126
|
it 'can enable, disable and get value for percentage of actors gate' do
|
@@ -182,9 +182,10 @@ RSpec.shared_examples_for 'a flipper adapter' do
|
|
182
182
|
end
|
183
183
|
|
184
184
|
it 'converts the actor value to a string' do
|
185
|
-
|
186
|
-
|
187
|
-
|
185
|
+
actor = Flipper::Actor.new(22)
|
186
|
+
expect(feature).not_to be_enabled(actor)
|
187
|
+
feature.enable_actor actor
|
188
|
+
expect(feature).to be_enabled(actor)
|
188
189
|
end
|
189
190
|
|
190
191
|
it 'converts group value to a string' do
|
@@ -295,9 +296,9 @@ RSpec.shared_examples_for 'a flipper adapter' do
|
|
295
296
|
|
296
297
|
it 'can double enable an actor without error' do
|
297
298
|
actor = Flipper::Actor.new('Flipper::Actor;22')
|
298
|
-
expect(
|
299
|
-
expect(
|
300
|
-
expect(
|
299
|
+
expect(feature.enable(actor)).to be(true)
|
300
|
+
expect(feature.enable(actor)).to be(true)
|
301
|
+
expect(feature).to be_enabled(actor)
|
301
302
|
end
|
302
303
|
|
303
304
|
it 'can double enable a group without error' do
|
@@ -104,19 +104,19 @@ module Flipper
|
|
104
104
|
actor22 = Flipper::Actor.new('22')
|
105
105
|
actor_asdf = Flipper::Actor.new('asdf')
|
106
106
|
|
107
|
-
assert_equal true, @
|
108
|
-
assert_equal true, @
|
107
|
+
assert_equal true, @feature.enable(actor22)
|
108
|
+
assert_equal true, @feature.enable(actor_asdf)
|
109
109
|
|
110
|
-
|
111
|
-
|
110
|
+
assert @feature.enabled?(actor22)
|
111
|
+
assert @feature.enabled?(actor_asdf)
|
112
112
|
|
113
|
-
|
114
|
-
|
115
|
-
|
113
|
+
assert_equal true, @feature.disable(actor22)
|
114
|
+
refute @feature.enabled?(actor22)
|
115
|
+
assert @feature.enabled?(actor_asdf)
|
116
116
|
|
117
|
-
assert_equal true, @
|
118
|
-
|
119
|
-
|
117
|
+
assert_equal true, @feature.disable(actor_asdf)
|
118
|
+
refute @feature.enabled?(actor22)
|
119
|
+
refute @feature.enabled?(actor_asdf)
|
120
120
|
end
|
121
121
|
|
122
122
|
def test_can_enable_disable_get_value_for_percentage_of_actors_gate
|
@@ -178,10 +178,10 @@ module Flipper
|
|
178
178
|
end
|
179
179
|
|
180
180
|
def test_converts_the_actor_value_to_a_string
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
181
|
+
actor = Flipper::Actor.new(22)
|
182
|
+
refute @feature.enabled?(actor)
|
183
|
+
@feature.enable_actor actor
|
184
|
+
assert @feature.enabled?(actor)
|
185
185
|
end
|
186
186
|
|
187
187
|
def test_converts_group_value_to_a_string
|
@@ -292,9 +292,9 @@ module Flipper
|
|
292
292
|
|
293
293
|
def test_can_double_enable_an_actor_without_error
|
294
294
|
actor = Flipper::Actor.new('Flipper::Actor;22')
|
295
|
-
assert_equal true, @
|
296
|
-
assert_equal true, @
|
297
|
-
|
295
|
+
assert_equal true, @feature.enable(actor)
|
296
|
+
assert_equal true, @feature.enable(actor)
|
297
|
+
assert @feature.enabled?(actor)
|
298
298
|
end
|
299
299
|
|
300
300
|
def test_can_double_enable_a_group_without_error
|
data/lib/flipper/test_help.rb
CHANGED
@@ -1,17 +1,24 @@
|
|
1
1
|
module Flipper
|
2
2
|
module TestHelp
|
3
|
+
extend self
|
4
|
+
|
3
5
|
def flipper_configure
|
4
|
-
#
|
5
|
-
|
6
|
+
# Use a shared Memory adapter for all tests. This is instantiated outside of the
|
7
|
+
# `configure` block so the same instance is returned in new threads.
|
8
|
+
adapter = Flipper::Adapters::Memory.new
|
6
9
|
|
7
10
|
Flipper.configure do |config|
|
8
|
-
config.adapter {
|
11
|
+
config.adapter { adapter }
|
9
12
|
config.default { Flipper.new(config.adapter) }
|
10
13
|
end
|
11
14
|
end
|
12
15
|
|
13
16
|
def flipper_reset
|
14
|
-
|
17
|
+
# Remove all features
|
18
|
+
Flipper.features.each(&:remove) rescue nil
|
19
|
+
|
20
|
+
# Reset previous DSL instance
|
21
|
+
Flipper.instance = nil
|
15
22
|
end
|
16
23
|
end
|
17
24
|
end
|
@@ -19,19 +26,17 @@ end
|
|
19
26
|
if defined?(RSpec) && RSpec.respond_to?(:configure)
|
20
27
|
RSpec.configure do |config|
|
21
28
|
config.include Flipper::TestHelp
|
22
|
-
config.before(:
|
23
|
-
|
24
|
-
flipper_configure
|
25
|
-
end
|
29
|
+
config.before(:suite) { Flipper::TestHelp.flipper_configure }
|
30
|
+
config.before(:each) { flipper_reset }
|
26
31
|
end
|
27
32
|
end
|
28
|
-
|
29
33
|
if defined?(ActiveSupport)
|
30
34
|
ActiveSupport.on_load(:active_support_test_case) do
|
35
|
+
Flipper::TestHelp.flipper_configure
|
36
|
+
|
31
37
|
ActiveSupport::TestCase.class_eval do
|
32
38
|
include Flipper::TestHelp
|
33
39
|
|
34
|
-
setup :flipper_configure
|
35
40
|
setup :flipper_reset
|
36
41
|
end
|
37
42
|
end
|
data/lib/flipper/typecast.rb
CHANGED
@@ -3,8 +3,8 @@ require "flipper/serializers/json"
|
|
3
3
|
require "flipper/serializers/gzip"
|
4
4
|
|
5
5
|
module Flipper
|
6
|
-
|
7
|
-
|
6
|
+
class Typecast
|
7
|
+
TRUTH_MAP = {
|
8
8
|
true => true,
|
9
9
|
1 => true,
|
10
10
|
'true' => true,
|
@@ -15,7 +15,7 @@ module Flipper
|
|
15
15
|
#
|
16
16
|
# Returns true or false.
|
17
17
|
def self.to_boolean(value)
|
18
|
-
!!
|
18
|
+
!!TRUTH_MAP[value]
|
19
19
|
end
|
20
20
|
|
21
21
|
# Internal: Convert value to an integer.
|
data/lib/flipper/version.rb
CHANGED
data/lib/flipper.rb
CHANGED
data/package-lock.json
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
{
|
2
|
+
"name": "flipper",
|
3
|
+
"lockfileVersion": 3,
|
4
|
+
"requires": true,
|
5
|
+
"packages": {
|
6
|
+
"": {
|
7
|
+
"hasInstallScript": true,
|
8
|
+
"dependencies": {
|
9
|
+
"@popperjs/core": "^2.11.8",
|
10
|
+
"bootstrap": "^5.3.3"
|
11
|
+
}
|
12
|
+
},
|
13
|
+
"node_modules/@popperjs/core": {
|
14
|
+
"version": "2.11.8",
|
15
|
+
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
|
16
|
+
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
|
17
|
+
"funding": {
|
18
|
+
"type": "opencollective",
|
19
|
+
"url": "https://opencollective.com/popperjs"
|
20
|
+
}
|
21
|
+
},
|
22
|
+
"node_modules/bootstrap": {
|
23
|
+
"version": "5.3.3",
|
24
|
+
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.3.tgz",
|
25
|
+
"integrity": "sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg==",
|
26
|
+
"funding": [
|
27
|
+
{
|
28
|
+
"type": "github",
|
29
|
+
"url": "https://github.com/sponsors/twbs"
|
30
|
+
},
|
31
|
+
{
|
32
|
+
"type": "opencollective",
|
33
|
+
"url": "https://opencollective.com/bootstrap"
|
34
|
+
}
|
35
|
+
],
|
36
|
+
"peerDependencies": {
|
37
|
+
"@popperjs/core": "^2.11.8"
|
38
|
+
}
|
39
|
+
}
|
40
|
+
}
|
41
|
+
}
|
data/package.json
ADDED
@@ -1,6 +1,15 @@
|
|
1
1
|
require 'flipper/adapters/http'
|
2
2
|
require 'flipper/adapters/pstore'
|
3
|
-
|
3
|
+
|
4
|
+
rack_handler = begin
|
5
|
+
# Rack 3+
|
6
|
+
require 'rackup/handler/webrick'
|
7
|
+
Rackup::Handler::WEBrick
|
8
|
+
rescue LoadError
|
9
|
+
require 'rack/handler/webrick'
|
10
|
+
Rack::Handler::WEBrick
|
11
|
+
end
|
12
|
+
|
4
13
|
|
5
14
|
FLIPPER_SPEC_API_PORT = ENV.fetch('FLIPPER_SPEC_API_PORT', 9001).to_i
|
6
15
|
|
@@ -36,7 +45,7 @@ RSpec.describe Flipper::Adapters::Http do
|
|
36
45
|
],
|
37
46
|
}
|
38
47
|
@server = WEBrick::HTTPServer.new(server_options)
|
39
|
-
@server.mount '/',
|
48
|
+
@server.mount '/', rack_handler, app
|
40
49
|
|
41
50
|
Thread.new { @server.start }
|
42
51
|
Timeout.timeout(1) { :wait until @started }
|
data/spec/flipper/cli_spec.rb
CHANGED
@@ -1,13 +1,33 @@
|
|
1
1
|
require "flipper/cli"
|
2
2
|
|
3
3
|
RSpec.describe Flipper::CLI do
|
4
|
+
let(:stdout) { StringIO.new }
|
5
|
+
let(:stderr) { StringIO.new }
|
6
|
+
let(:cli) { Flipper::CLI.new(stdout: stdout, stderr: stderr) }
|
7
|
+
|
8
|
+
before do
|
9
|
+
# Prentend stdout/stderr a TTY to test colorization
|
10
|
+
allow(stdout).to receive(:tty?).and_return(true)
|
11
|
+
allow(stderr).to receive(:tty?).and_return(true)
|
12
|
+
end
|
13
|
+
|
4
14
|
# Infer the command from the description
|
5
15
|
subject(:argv) do
|
6
16
|
descriptions = self.class.parent_groups.map {|g| g.metadata[:description_args] }.reverse.flatten.drop(1)
|
7
17
|
descriptions.map { |arg| Shellwords.split(arg) }.flatten
|
8
18
|
end
|
9
19
|
|
10
|
-
subject
|
20
|
+
subject do
|
21
|
+
status = 0
|
22
|
+
|
23
|
+
begin
|
24
|
+
cli.run(argv)
|
25
|
+
rescue SystemExit => e
|
26
|
+
status = e.status
|
27
|
+
end
|
28
|
+
|
29
|
+
OpenStruct.new(status: status, stdout: stdout.string, stderr: stderr.string)
|
30
|
+
end
|
11
31
|
|
12
32
|
before do
|
13
33
|
ENV["FLIPPER_REQUIRE"] = "./spec/fixtures/environment"
|
@@ -16,14 +36,14 @@ RSpec.describe Flipper::CLI do
|
|
16
36
|
describe "enable" do
|
17
37
|
describe "feature" do
|
18
38
|
it do
|
19
|
-
expect(subject).to have_attributes(status: 0, stdout: /feature.*enabled/)
|
39
|
+
expect(subject).to have_attributes(status: 0, stdout: /feature.*\e\[32m.*enabled/)
|
20
40
|
expect(Flipper).to be_enabled(:feature)
|
21
41
|
end
|
22
42
|
end
|
23
43
|
|
24
44
|
describe "-a User;1 feature" do
|
25
45
|
it do
|
26
|
-
expect(subject).to have_attributes(status: 0, stdout: /feature.*enabled.*User;1/m)
|
46
|
+
expect(subject).to have_attributes(status: 0, stdout: /feature.*\e\[33m.*enabled.*User;1/m)
|
27
47
|
expect(Flipper).to be_enabled(:feature, Flipper::Actor.new("User;1"))
|
28
48
|
end
|
29
49
|
end
|
@@ -141,24 +161,4 @@ RSpec.describe Flipper::CLI do
|
|
141
161
|
it { should have_attributes(status: 0, stdout: /enabled.*admins/m) }
|
142
162
|
end
|
143
163
|
end
|
144
|
-
|
145
|
-
def run(argv)
|
146
|
-
original_stdout = $stdout
|
147
|
-
original_stderr = $stderr
|
148
|
-
|
149
|
-
$stdout = StringIO.new
|
150
|
-
$stderr = StringIO.new
|
151
|
-
status = 0
|
152
|
-
|
153
|
-
begin
|
154
|
-
Flipper::CLI.run(argv)
|
155
|
-
rescue SystemExit => e
|
156
|
-
status = e.status
|
157
|
-
end
|
158
|
-
|
159
|
-
OpenStruct.new(status: status, stdout: $stdout.string, stderr: $stderr.string)
|
160
|
-
ensure
|
161
|
-
$stdout = original_stdout
|
162
|
-
$stderr = original_stderr
|
163
|
-
end
|
164
164
|
end
|
@@ -12,16 +12,16 @@ RSpec.describe Flipper::Cloud::Configuration do
|
|
12
12
|
end
|
13
13
|
|
14
14
|
it "can set token from ENV var" do
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
end
|
15
|
+
ENV["FLIPPER_CLOUD_TOKEN"] = "from_env"
|
16
|
+
instance = described_class.new(required_options.reject { |k, v| k == :token })
|
17
|
+
expect(instance.token).to eq("from_env")
|
19
18
|
end
|
20
19
|
|
21
20
|
it "can set instrumenter" do
|
22
21
|
instrumenter = Object.new
|
23
22
|
instance = described_class.new(required_options.merge(instrumenter: instrumenter))
|
24
|
-
expect(instance.instrumenter).to
|
23
|
+
expect(instance.instrumenter).to be_a(Flipper::Cloud::Telemetry::Instrumenter)
|
24
|
+
expect(instance.instrumenter.instrumenter).to be(instrumenter)
|
25
25
|
end
|
26
26
|
|
27
27
|
it "can set read_timeout" do
|
@@ -30,10 +30,9 @@ RSpec.describe Flipper::Cloud::Configuration do
|
|
30
30
|
end
|
31
31
|
|
32
32
|
it "can set read_timeout from ENV var" do
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
end
|
33
|
+
ENV["FLIPPER_CLOUD_READ_TIMEOUT"] = "9"
|
34
|
+
instance = described_class.new(required_options.reject { |k, v| k == :read_timeout })
|
35
|
+
expect(instance.read_timeout).to eq(9)
|
37
36
|
end
|
38
37
|
|
39
38
|
it "can set open_timeout" do
|
@@ -42,10 +41,9 @@ RSpec.describe Flipper::Cloud::Configuration do
|
|
42
41
|
end
|
43
42
|
|
44
43
|
it "can set open_timeout from ENV var" do
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
end
|
44
|
+
ENV["FLIPPER_CLOUD_OPEN_TIMEOUT"] = "9"
|
45
|
+
instance = described_class.new(required_options.reject { |k, v| k == :open_timeout })
|
46
|
+
expect(instance.open_timeout).to eq(9)
|
49
47
|
end
|
50
48
|
|
51
49
|
it "can set write_timeout" do
|
@@ -54,10 +52,9 @@ RSpec.describe Flipper::Cloud::Configuration do
|
|
54
52
|
end
|
55
53
|
|
56
54
|
it "can set write_timeout from ENV var" do
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
end
|
55
|
+
ENV["FLIPPER_CLOUD_WRITE_TIMEOUT"] = "9"
|
56
|
+
instance = described_class.new(required_options.reject { |k, v| k == :write_timeout })
|
57
|
+
expect(instance.write_timeout).to eq(9)
|
61
58
|
end
|
62
59
|
|
63
60
|
it "can set sync_interval" do
|
@@ -66,10 +63,9 @@ RSpec.describe Flipper::Cloud::Configuration do
|
|
66
63
|
end
|
67
64
|
|
68
65
|
it "can set sync_interval from ENV var" do
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
end
|
66
|
+
ENV["FLIPPER_CLOUD_SYNC_INTERVAL"] = "15"
|
67
|
+
instance = described_class.new(required_options.reject { |k, v| k == :sync_interval })
|
68
|
+
expect(instance.sync_interval).to eq(15)
|
73
69
|
end
|
74
70
|
|
75
71
|
it "passes sync_interval into sync adapter" do
|
@@ -87,10 +83,9 @@ RSpec.describe Flipper::Cloud::Configuration do
|
|
87
83
|
end
|
88
84
|
|
89
85
|
it "defaults debug_output to STDOUT if FLIPPER_CLOUD_DEBUG_OUTPUT_STDOUT set to true" do
|
90
|
-
|
91
|
-
|
86
|
+
ENV["FLIPPER_CLOUD_DEBUG_OUTPUT_STDOUT"] = "true"
|
87
|
+
instance = described_class.new(required_options)
|
92
88
|
expect(instance.debug_output).to eq(STDOUT)
|
93
|
-
end
|
94
89
|
end
|
95
90
|
|
96
91
|
it "defaults adapter block" do
|
@@ -128,10 +123,9 @@ RSpec.describe Flipper::Cloud::Configuration do
|
|
128
123
|
end
|
129
124
|
|
130
125
|
it "can override URL using ENV var" do
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
end
|
126
|
+
ENV["FLIPPER_CLOUD_URL"] = "https://example.com"
|
127
|
+
instance = described_class.new(required_options.reject { |k, v| k == :url })
|
128
|
+
expect(instance.url).to eq("https://example.com")
|
135
129
|
end
|
136
130
|
|
137
131
|
it "defaults sync_method to :poll" do
|
@@ -150,12 +144,11 @@ RSpec.describe Flipper::Cloud::Configuration do
|
|
150
144
|
end
|
151
145
|
|
152
146
|
it "sets sync_method to :webhook if FLIPPER_CLOUD_SYNC_SECRET set" do
|
153
|
-
|
154
|
-
|
147
|
+
ENV["FLIPPER_CLOUD_SYNC_SECRET"] = "abc"
|
148
|
+
instance = described_class.new(required_options)
|
155
149
|
|
156
|
-
|
157
|
-
|
158
|
-
end
|
150
|
+
expect(instance.sync_method).to eq(:webhook)
|
151
|
+
expect(instance.adapter).to be_instance_of(Flipper::Adapters::DualWrite)
|
159
152
|
end
|
160
153
|
|
161
154
|
it "can set sync_secret" do
|
@@ -164,10 +157,9 @@ RSpec.describe Flipper::Cloud::Configuration do
|
|
164
157
|
end
|
165
158
|
|
166
159
|
it "can override sync_secret using ENV var" do
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
end
|
160
|
+
ENV["FLIPPER_CLOUD_SYNC_SECRET"] = "from_env"
|
161
|
+
instance = described_class.new(required_options.reject { |k, v| k == :sync_secret })
|
162
|
+
expect(instance.sync_secret).to eq("from_env")
|
171
163
|
end
|
172
164
|
|
173
165
|
it "can sync with cloud" do
|
@@ -49,19 +49,18 @@ RSpec.describe Flipper::Cloud::Telemetry::BackoffPolicy do
|
|
49
49
|
end
|
50
50
|
|
51
51
|
it "from env" do
|
52
|
-
|
52
|
+
ENV.update(
|
53
53
|
"FLIPPER_BACKOFF_MIN_TIMEOUT_MS" => "1000",
|
54
54
|
"FLIPPER_BACKOFF_MAX_TIMEOUT_MS" => "2000",
|
55
55
|
"FLIPPER_BACKOFF_MULTIPLIER" => "1.9",
|
56
56
|
"FLIPPER_BACKOFF_RANDOMIZATION_FACTOR" => "0.1",
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
end
|
57
|
+
)
|
58
|
+
|
59
|
+
policy = described_class.new
|
60
|
+
expect(policy.min_timeout_ms).to eq(1000)
|
61
|
+
expect(policy.max_timeout_ms).to eq(2000)
|
62
|
+
expect(policy.multiplier).to eq(1.9)
|
63
|
+
expect(policy.randomization_factor).to eq(0.1)
|
65
64
|
end
|
66
65
|
end
|
67
66
|
|