flipper-active_support_cache_store 1.2.2 → 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
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bbb7450e9a2de26da717b62bffb2f49b7dbb7bd8afd845630793d0d9b140360e
|
4
|
+
data.tar.gz: c5497eef3c7643330268af315b027e31e6b7021849c03f503eb8410684f64160
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c044942a4c2a7b737fc84dcb380858f93487ef08c5662c519074915099e8cbb3a1eb2ace3fe5da4a385c977115c58175ca50a2a58a80d82e199009dd34ec2216
|
7
|
+
data.tar.gz: fe145df6098e3926b16b10e6607f4629492822cda6ac2b395960b12315961033955a52f653a9dea6b30111456bc90c358a6ce84814c978448794bdb40647ed28
|
@@ -1,146 +1,79 @@
|
|
1
1
|
require 'flipper'
|
2
|
+
require 'flipper/adapters/cache_base'
|
2
3
|
require 'active_support/notifications'
|
3
4
|
|
4
5
|
module Flipper
|
5
6
|
module Adapters
|
6
7
|
# Public: Adapter that wraps another adapter with the ability to cache
|
7
8
|
# adapter calls in ActiveSupport::ActiveSupportCacheStore caches.
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
@write_options[:expires_in] = expires_in if expires_in
|
9
|
+
class ActiveSupportCacheStore < CacheBase
|
10
|
+
def initialize(adapter, cache, ttl = nil, expires_in: :none_provided, write_through: false, prefix: nil)
|
11
|
+
if expires_in == :none_provided
|
12
|
+
ttl ||= nil
|
13
|
+
else
|
14
|
+
warn "DEPRECATION WARNING: The `expires_in` kwarg is deprecated for " +
|
15
|
+
"Flipper::Adapters::ActiveSupportCacheStore and will be removed " +
|
16
|
+
"in the next major version. Please pass in expires in as third " +
|
17
|
+
"argument instead."
|
18
|
+
ttl = expires_in
|
19
|
+
end
|
20
|
+
super(adapter, cache, ttl, prefix: prefix)
|
21
21
|
@write_through = write_through
|
22
|
-
|
23
|
-
@cache_version = 'v1'.freeze
|
24
|
-
@namespace = "flipper/#{@cache_version}".freeze
|
25
|
-
@features_key = "#{@namespace}/features".freeze
|
26
|
-
@get_all_key = "#{@namespace}/get_all".freeze
|
27
|
-
end
|
28
|
-
|
29
|
-
# Public
|
30
|
-
def features
|
31
|
-
read_feature_keys
|
32
22
|
end
|
33
23
|
|
34
|
-
# Public
|
35
|
-
def add(feature)
|
36
|
-
result = @adapter.add(feature)
|
37
|
-
@cache.delete(@features_key)
|
38
|
-
result
|
39
|
-
end
|
40
|
-
|
41
|
-
## Public
|
42
24
|
def remove(feature)
|
43
|
-
result = @adapter.remove(feature)
|
44
|
-
@cache.delete(@features_key)
|
45
|
-
|
46
25
|
if @write_through
|
47
|
-
@
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
result
|
53
|
-
end
|
54
|
-
|
55
|
-
## Public
|
56
|
-
def clear(feature)
|
57
|
-
result = @adapter.clear(feature)
|
58
|
-
@cache.delete(key_for(feature.key))
|
59
|
-
result
|
60
|
-
end
|
61
|
-
|
62
|
-
## Public
|
63
|
-
def get(feature)
|
64
|
-
@cache.fetch(key_for(feature.key), @write_options) do
|
65
|
-
@adapter.get(feature)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
def get_multi(features)
|
70
|
-
read_many_features(features)
|
71
|
-
end
|
72
|
-
|
73
|
-
def get_all
|
74
|
-
if @cache.write(@get_all_key, Time.now.to_i, @write_options.merge(unless_exist: true))
|
75
|
-
response = @adapter.get_all
|
76
|
-
response.each do |key, value|
|
77
|
-
@cache.write(key_for(key), value, @write_options)
|
78
|
-
end
|
79
|
-
@cache.write(@features_key, response.keys.to_set, @write_options)
|
80
|
-
response
|
26
|
+
result = @adapter.remove(feature)
|
27
|
+
expire_features_cache
|
28
|
+
cache_write feature_cache_key(feature.key), default_config
|
29
|
+
result
|
81
30
|
else
|
82
|
-
|
83
|
-
read_many_features(features)
|
31
|
+
super
|
84
32
|
end
|
85
33
|
end
|
86
34
|
|
87
|
-
## Public
|
88
35
|
def enable(feature, gate, thing)
|
89
|
-
result = @adapter.enable(feature, gate, thing)
|
90
|
-
|
91
36
|
if @write_through
|
92
|
-
|
37
|
+
result = @adapter.enable(feature, gate, thing)
|
38
|
+
cache_write feature_cache_key(feature.key), @adapter.get(feature)
|
39
|
+
result
|
93
40
|
else
|
94
|
-
|
41
|
+
super
|
95
42
|
end
|
96
|
-
|
97
|
-
result
|
98
43
|
end
|
99
44
|
|
100
|
-
## Public
|
101
45
|
def disable(feature, gate, thing)
|
102
|
-
result = @adapter.disable(feature, gate, thing)
|
103
|
-
|
104
46
|
if @write_through
|
105
|
-
|
47
|
+
result = @adapter.disable(feature, gate, thing)
|
48
|
+
cache_write feature_cache_key(feature.key), @adapter.get(feature)
|
49
|
+
result
|
106
50
|
else
|
107
|
-
|
51
|
+
super
|
108
52
|
end
|
109
|
-
|
110
|
-
result
|
111
53
|
end
|
112
54
|
|
113
55
|
private
|
114
56
|
|
115
|
-
def
|
116
|
-
|
57
|
+
def cache_fetch(key, &block)
|
58
|
+
@cache.fetch(key, write_options, &block)
|
117
59
|
end
|
118
60
|
|
119
|
-
|
120
|
-
|
121
|
-
@cache.fetch(@features_key, @write_options) { @adapter.features }
|
61
|
+
def cache_read_multi(keys)
|
62
|
+
@cache.read_multi(*keys)
|
122
63
|
end
|
123
64
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
keys = features.map { |feature| key_for(feature.key) }
|
128
|
-
cache_result = @cache.read_multi(*keys)
|
129
|
-
uncached_features = features.reject { |feature| cache_result[key_for(feature)] }
|
65
|
+
def cache_write(key, value)
|
66
|
+
@cache.write(key, value, write_options)
|
67
|
+
end
|
130
68
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
@cache.write(key_for(key), value, @write_options)
|
135
|
-
cache_result[key_for(key)] = value
|
136
|
-
end
|
137
|
-
end
|
69
|
+
def cache_delete(key)
|
70
|
+
@cache.delete(key)
|
71
|
+
end
|
138
72
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
result
|
73
|
+
def write_options
|
74
|
+
write_options = {}
|
75
|
+
write_options[:expires_in] = @ttl if @ttl
|
76
|
+
write_options
|
144
77
|
end
|
145
78
|
end
|
146
79
|
end
|
data/lib/flipper/version.rb
CHANGED
@@ -8,7 +8,7 @@ RSpec.describe Flipper::Adapters::ActiveSupportCacheStore do
|
|
8
8
|
end
|
9
9
|
let(:cache) { ActiveSupport::Cache::MemoryStore.new }
|
10
10
|
let(:write_through) { false }
|
11
|
-
let(:adapter) { described_class.new(memory_adapter, cache,
|
11
|
+
let(:adapter) { described_class.new(memory_adapter, cache, 10, write_through: write_through) }
|
12
12
|
let(:flipper) { Flipper.new(adapter) }
|
13
13
|
|
14
14
|
subject { adapter }
|
@@ -19,6 +19,92 @@ RSpec.describe Flipper::Adapters::ActiveSupportCacheStore do
|
|
19
19
|
|
20
20
|
it_should_behave_like 'a flipper adapter'
|
21
21
|
|
22
|
+
it "knows ttl" do
|
23
|
+
expect(adapter.ttl).to eq(10)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "knows ttl when only expires_in provided" do
|
27
|
+
silence do
|
28
|
+
adapter = described_class.new(memory_adapter, cache, expires_in: 10)
|
29
|
+
expect(adapter.ttl).to eq(10)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
it "knows ttl when ttl and expires_in are provided" do
|
34
|
+
silence do
|
35
|
+
adapter = described_class.new(memory_adapter, cache, 200, expires_in: 10)
|
36
|
+
expect(adapter.ttl).to eq(10)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
it "knows default when no ttl or expires_in provided" do
|
41
|
+
adapter = described_class.new(memory_adapter, cache)
|
42
|
+
expect(adapter.ttl).to be(nil)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "knows features_cache_key" do
|
46
|
+
expect(adapter.features_cache_key).to eq("flipper/v1/features")
|
47
|
+
end
|
48
|
+
|
49
|
+
it "can expire features cache" do
|
50
|
+
# cache the features
|
51
|
+
adapter.features
|
52
|
+
expect(cache.read("flipper/v1/features")).not_to be(nil)
|
53
|
+
|
54
|
+
# expire cache
|
55
|
+
adapter.expire_features_cache
|
56
|
+
expect(cache.read("flipper/v1/features")).to be(nil)
|
57
|
+
end
|
58
|
+
|
59
|
+
it "can expire feature cache" do
|
60
|
+
# cache the features
|
61
|
+
adapter.get(flipper[:stats])
|
62
|
+
expect(cache.read("flipper/v1/feature/stats")).not_to be(nil)
|
63
|
+
|
64
|
+
# expire cache
|
65
|
+
adapter.expire_feature_cache("stats")
|
66
|
+
expect(cache.read("flipper/v1/feature/stats")).to be(nil)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "can generate feature cache key" do
|
70
|
+
expect(adapter.feature_cache_key("stats")).to eq("flipper/v1/feature/stats")
|
71
|
+
end
|
72
|
+
|
73
|
+
context "when using a prefix" do
|
74
|
+
let(:adapter) { described_class.new(memory_adapter, cache, 10, prefix: "foo/") }
|
75
|
+
it_should_behave_like 'a flipper adapter'
|
76
|
+
|
77
|
+
it "knows features_cache_key" do
|
78
|
+
expect(adapter.features_cache_key).to eq("foo/flipper/v1/features")
|
79
|
+
end
|
80
|
+
|
81
|
+
it "can generate feature cache key" do
|
82
|
+
expect(adapter.feature_cache_key("stats")).to eq("foo/flipper/v1/feature/stats")
|
83
|
+
end
|
84
|
+
|
85
|
+
it "uses the prefix for all keys" do
|
86
|
+
# check individual feature get cached with prefix
|
87
|
+
adapter.get(flipper[:stats])
|
88
|
+
expect(cache.read("foo/flipper/v1/feature/stats")).not_to be(nil)
|
89
|
+
|
90
|
+
# check individual feature expired with prefix
|
91
|
+
adapter.remove(flipper[:stats])
|
92
|
+
expect(cache.read("foo/flipper/v1/feature/stats")).to be(nil)
|
93
|
+
|
94
|
+
# enable some stuff
|
95
|
+
flipper.enable_percentage_of_actors(:search, 10)
|
96
|
+
flipper.enable(:stats)
|
97
|
+
|
98
|
+
# populate the cache
|
99
|
+
adapter.get_all
|
100
|
+
|
101
|
+
# verify cached with prefix
|
102
|
+
expect(cache.read("foo/flipper/v1/features")).to eq(Set["stats", "search"])
|
103
|
+
expect(cache.read("foo/flipper/v1/feature/search")[:percentage_of_actors]).to eq("10")
|
104
|
+
expect(cache.read("foo/flipper/v1/feature/stats")[:boolean]).to eq("true")
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
22
108
|
describe '#remove' do
|
23
109
|
let(:feature) { flipper[:stats] }
|
24
110
|
|
@@ -130,17 +216,19 @@ RSpec.describe Flipper::Adapters::ActiveSupportCacheStore do
|
|
130
216
|
adapter.get_all
|
131
217
|
expect(cache.read("flipper/v1/feature/#{stats.key}")[:boolean]).to eq('true')
|
132
218
|
expect(cache.read("flipper/v1/feature/#{search.key}")[:boolean]).to be(nil)
|
133
|
-
expect(cache.read("flipper/v1/
|
219
|
+
expect(cache.read("flipper/v1/features")).to eq(Set["stats", "search"])
|
134
220
|
end
|
135
221
|
|
136
222
|
it 'returns same result when already cached' do
|
137
223
|
expect(adapter.get_all).to eq(adapter.get_all)
|
138
224
|
end
|
139
225
|
|
140
|
-
it 'only invokes
|
226
|
+
it 'only invokes two calls to wrapped adapter (for features set and gate data for each feature in set)' do
|
141
227
|
memory_adapter.reset
|
142
228
|
5.times { adapter.get_all }
|
143
|
-
expect(memory_adapter.count(:
|
229
|
+
expect(memory_adapter.count(:features)).to eq(1)
|
230
|
+
expect(memory_adapter.count(:get_multi)).to eq(1)
|
231
|
+
expect(memory_adapter.count).to eq(2)
|
144
232
|
end
|
145
233
|
end
|
146
234
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flipper-active_support_cache_store
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0.pre
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Nunemaker
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-03-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: flipper
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 1.
|
19
|
+
version: 1.3.0.pre
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 1.
|
26
|
+
version: 1.3.0.pre
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: activesupport
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -63,7 +63,7 @@ metadata:
|
|
63
63
|
homepage_uri: https://www.flippercloud.io
|
64
64
|
source_code_uri: https://github.com/flippercloud/flipper
|
65
65
|
bug_tracker_uri: https://github.com/flippercloud/flipper/issues
|
66
|
-
changelog_uri: https://github.com/flippercloud/flipper/releases/tag/v1.
|
66
|
+
changelog_uri: https://github.com/flippercloud/flipper/releases/tag/v1.3.0.pre
|
67
67
|
post_install_message:
|
68
68
|
rdoc_options: []
|
69
69
|
require_paths:
|