Skip to content

Commit 8da950b

Browse files
authored
Preserve wrapped adapter import semantics (#1049)
1 parent d240e52 commit 8da950b

2 files changed

Lines changed: 77 additions & 0 deletions

File tree

‎lib/flipper/adapters/cache_base.rb‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,19 @@ def get_all(**kwargs)
9898
}
9999
end
100100

101+
# Public
102+
def import(source)
103+
feature_keys = @adapter.features
104+
result = @adapter.import(source)
105+
return result unless result
106+
107+
feature_keys |= @adapter.features
108+
109+
feature_keys.each { |key| cache_delete feature_cache_key(key) }
110+
expire_features_cache
111+
result
112+
end
113+
101114
# Public
102115
def enable(feature, gate, thing)
103116
result = @adapter.enable(feature, gate, thing)

‎spec/flipper/adapters/active_support_cache_store_spec.rb‎

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,70 @@
280280
end
281281
end
282282

283+
describe '#import' do
284+
it "delegates to the wrapped adapter's import" do
285+
source = Flipper::Adapters::Memory.new
286+
result = Object.new
287+
expect(memory_adapter).to receive(:import).with(source).and_return(result)
288+
289+
expect(adapter.import(source)).to be(result)
290+
end
291+
292+
it 'expires caches for changed, added, and removed features' do
293+
flipper[:changed].add
294+
flipper[:removed].enable
295+
296+
source_adapter = Flipper::Adapters::Memory.new
297+
source_flipper = Flipper.new(source_adapter)
298+
source_flipper[:changed].enable
299+
source_flipper[:added].enable
300+
301+
[:changed, :added, :removed].each { |key| adapter.get(flipper[key]) }
302+
adapter.features
303+
adapter.get_all
304+
305+
expect(adapter.import(source_adapter)).to be(true)
306+
expect(cache.read('flipper/v1/feature/changed')).to be_nil
307+
expect(cache.read('flipper/v1/feature/added')).to be_nil
308+
expect(cache.read('flipper/v1/feature/removed')).to be_nil
309+
expect(cache.read('flipper/v1/features')).to be_nil
310+
expect(cache.read('flipper/v1/get_all')).to be_nil
311+
expect(flipper[:changed]).to be_enabled
312+
expect(flipper[:added]).to be_enabled
313+
expect(flipper[:removed]).not_to be_enabled
314+
end
315+
316+
it 'preserves import errors without expiring caches' do
317+
flipper[:existing].enable
318+
adapter.get(flipper[:existing])
319+
adapter.features
320+
adapter.get_all
321+
322+
cached_feature = cache.read('flipper/v1/feature/existing')
323+
cached_features = cache.read('flipper/v1/features')
324+
cached_get_all = cache.read('flipper/v1/get_all')
325+
error = Class.new(StandardError).new('import failed')
326+
allow(memory_adapter).to receive(:import).and_raise(error)
327+
expect(cache).not_to receive(:delete)
328+
329+
expect { adapter.import(Flipper::Adapters::Memory.new) }
330+
.to raise_error { |raised| expect(raised).to be(error) }
331+
expect(cache.read('flipper/v1/feature/existing')).to eq(cached_feature)
332+
expect(cache.read('flipper/v1/features')).to eq(cached_features)
333+
expect(cache.read('flipper/v1/get_all')).to eq(cached_get_all)
334+
end
335+
336+
it 'does not expire caches when the wrapped adapter declines the import' do
337+
flipper[:existing].enable
338+
adapter.get(flipper[:existing])
339+
allow(memory_adapter).to receive(:import).and_return(false)
340+
expect(cache).not_to receive(:delete)
341+
342+
expect(adapter.import(Flipper::Adapters::Memory.new)).to be(false)
343+
expect(cache.read('flipper/v1/feature/existing')).not_to be_nil
344+
end
345+
end
346+
283347
describe '#name' do
284348
it 'is active_support_cache_store' do
285349
expect(subject.name).to be(:active_support_cache_store)

0 commit comments

Comments
 (0)