豆豆友情提示:这是一个非官方 GitHub 代理镜像,主要用于网络测试或访问加速。请勿在此进行登录、注册或处理任何敏感信息。进行这些操作请务必访问官方网站 github.com。 Raw 内容也通过此代理提供。
Skip to content

Commit 7f4daa5

Browse files
authored
Merge pull request #982 from flippercloud/strict-adapter-sync-mode
Add sync mode bypass to Strict adapter
2 parents 7e6ce79 + 7621476 commit 7f4daa5

File tree

3 files changed

+96
-5
lines changed

3 files changed

+96
-5
lines changed

lib/flipper/adapters/strict.rb

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,40 @@ def initialize(name)
1010
end
1111
end
1212

13+
class << self
14+
# Returns whether sync mode is enabled for the current thread.
15+
# When sync mode is enabled, strict checks are not enforced,
16+
# allowing sync operations to add features and bring local state
17+
# in line with remote state.
18+
def sync_mode
19+
Thread.current[:flipper_strict_sync_mode]
20+
end
21+
22+
def sync_mode=(value)
23+
Thread.current[:flipper_strict_sync_mode] = value
24+
end
25+
26+
# Executes a block with sync mode enabled. Strict checks will
27+
# not be enforced within the block.
28+
def with_sync_mode
29+
old_value = sync_mode
30+
self.sync_mode = true
31+
yield
32+
ensure
33+
self.sync_mode = old_value
34+
end
35+
end
36+
1337
def initialize(adapter, handler = nil, &block)
1438
super(adapter)
1539
@handler = block || handler
1640
end
1741

42+
def add(feature)
43+
assert_feature_exists(feature) unless self.class.sync_mode
44+
super
45+
end
46+
1847
def get(feature)
1948
assert_feature_exists(feature)
2049
super
@@ -28,6 +57,7 @@ def get_multi(features)
2857
private
2958

3059
def assert_feature_exists(feature)
60+
return if self.class.sync_mode
3161
return if @adapter.features.include?(feature.key)
3262

3363
case handler

lib/flipper/adapters/sync/synchronizer.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
require "flipper/feature"
22
require "flipper/gate_values"
33
require "flipper/adapters/actor_limit"
4+
require "flipper/adapters/strict"
45
require "flipper/adapters/sync/feature_synchronizer"
56

67
module Flipper
@@ -29,7 +30,9 @@ def initialize(local, remote, options = {})
2930
# Public: Forces a sync.
3031
def call
3132
@instrumenter.instrument("synchronizer_call.flipper") do
32-
Flipper::Adapters::ActorLimit.with_sync_mode { sync }
33+
Flipper::Adapters::Strict.with_sync_mode do
34+
Flipper::Adapters::ActorLimit.with_sync_mode { sync }
35+
end
3336
end
3437
end
3538

spec/flipper/adapters/strict_spec.rb

Lines changed: 62 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,23 +21,35 @@
2121
expect { subject.get_multi([feature]) }.to raise_error(Flipper::Adapters::Strict::NotFound)
2222
end
2323
end
24+
25+
context "#add" do
26+
it "raises an error for unknown feature" do
27+
expect { subject.add(feature) }.to raise_error(Flipper::Adapters::Strict::NotFound)
28+
end
29+
end
2430
end
2531
end
2632

2733
context "handler = :warn" do
2834
subject { described_class.new(Flipper::Adapters::Memory.new, :warn) }
2935

3036
context "#get" do
31-
it "raises an error for unknown feature" do
37+
it "warns for unknown feature" do
3238
expect(capture_output { subject.get(feature) }).to match(/Could not find feature "unknown"/)
3339
end
3440
end
3541

3642
context "#get_multi" do
37-
it "raises an error for unknown feature" do
43+
it "warns for unknown feature" do
3844
expect(capture_output { subject.get_multi([feature]) }).to match(/Could not find feature "unknown"/)
3945
end
4046
end
47+
48+
context "#add" do
49+
it "warns for unknown feature" do
50+
expect(capture_output { subject.add(feature) }).to match(/Could not find feature "unknown"/)
51+
end
52+
end
4153
end
4254

4355
context "handler = Block" do
@@ -48,17 +60,63 @@
4860

4961

5062
context "#get" do
51-
it "raises an error for unknown feature" do
63+
it "calls block for unknown feature" do
5264
subject.get(feature)
5365
expect(unknown_features).to eq(["unknown"])
5466
end
5567
end
5668

5769
context "#get_multi" do
58-
it "raises an error for unknown feature" do
70+
it "calls block for unknown feature" do
5971
subject.get_multi([flipper[:foo], flipper[:bar]])
6072
expect(unknown_features).to eq(["foo", "bar"])
6173
end
6274
end
75+
76+
context "#add" do
77+
it "calls block for unknown feature" do
78+
subject.add(feature)
79+
expect(unknown_features).to eq(["unknown"])
80+
end
81+
end
82+
end
83+
84+
describe ".with_sync_mode" do
85+
subject { described_class.new(Flipper::Adapters::Memory.new, :raise) }
86+
87+
it "bypasses strict checks for add" do
88+
described_class.with_sync_mode do
89+
expect { subject.add(feature) }.not_to raise_error
90+
end
91+
end
92+
93+
it "bypasses strict checks for get" do
94+
described_class.with_sync_mode do
95+
expect { subject.get(feature) }.not_to raise_error
96+
end
97+
end
98+
99+
it "bypasses strict checks for get_multi" do
100+
described_class.with_sync_mode do
101+
expect { subject.get_multi([feature]) }.not_to raise_error
102+
end
103+
end
104+
105+
it "restores previous sync mode after block" do
106+
described_class.with_sync_mode do
107+
# inside sync mode
108+
end
109+
expect { subject.add(feature) }.to raise_error(Flipper::Adapters::Strict::NotFound)
110+
end
111+
112+
it "restores previous sync mode even on error" do
113+
begin
114+
described_class.with_sync_mode do
115+
raise "boom"
116+
end
117+
rescue RuntimeError
118+
end
119+
expect { subject.add(feature) }.to raise_error(Flipper::Adapters::Strict::NotFound)
120+
end
63121
end
64122
end

0 commit comments

Comments
 (0)