flipper-redis 0.11.0.beta9 → 0.11.0.rc1
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/lib/flipper/adapters/redis.rb +22 -7
- data/lib/flipper/adapters/redis_cache.rb +39 -14
- data/lib/flipper/version.rb +1 -1
- data/spec/flipper/adapters/redis_cache_spec.rb +42 -9
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a5f75cfdfc5971f034dc0769596d86a430a06020
|
4
|
+
data.tar.gz: 165e82e9aa9662d4562e693c09669bb1a1d0e7d9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cc5dc1840fce96636a8ee8a96b8fc5e1fd6042d8e9b84174eb8fef9e1bcdec4f1cc22ef44aac6007788b4860aa0caedb43e697d51d54889d5b1fc76df88f9b87
|
7
|
+
data.tar.gz: 373bbbb5b19a40ad62bd548c7c5d23b497ac86673d8e5cf2d01615c096144346e4f7e4c149ca50ede59a322491f875a529387fc5a1c02826f3e48e635fc7db48
|
@@ -23,7 +23,7 @@ module Flipper
|
|
23
23
|
|
24
24
|
# Public: The set of known features.
|
25
25
|
def features
|
26
|
-
|
26
|
+
read_feature_keys
|
27
27
|
end
|
28
28
|
|
29
29
|
# Public: Adds a feature to the set of known features.
|
@@ -56,12 +56,12 @@ module Flipper
|
|
56
56
|
end
|
57
57
|
|
58
58
|
def get_multi(features)
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
59
|
+
read_many_features(features)
|
60
|
+
end
|
61
|
+
|
62
|
+
def get_all
|
63
|
+
features = read_feature_keys.map { |key| Flipper::Feature.new(key, self) }
|
64
|
+
read_many_features(features)
|
65
65
|
end
|
66
66
|
|
67
67
|
# Public: Enables a gate for a given thing.
|
@@ -106,6 +106,21 @@ module Flipper
|
|
106
106
|
true
|
107
107
|
end
|
108
108
|
|
109
|
+
private
|
110
|
+
|
111
|
+
def read_many_features(features)
|
112
|
+
docs = docs_for(features)
|
113
|
+
result = {}
|
114
|
+
features.zip(docs) do |feature, doc|
|
115
|
+
result[feature.key] = result_for_feature(feature, doc)
|
116
|
+
end
|
117
|
+
result
|
118
|
+
end
|
119
|
+
|
120
|
+
def read_feature_keys
|
121
|
+
@client.smembers(FeaturesKey).to_set
|
122
|
+
end
|
123
|
+
|
109
124
|
# Private: Gets a hash of fields => values for the given feature.
|
110
125
|
#
|
111
126
|
# Returns a Hash of fields => values.
|
@@ -10,6 +10,7 @@ module Flipper
|
|
10
10
|
Version = 'v1'.freeze
|
11
11
|
Namespace = "flipper/#{Version}".freeze
|
12
12
|
FeaturesKey = "#{Namespace}/features".freeze
|
13
|
+
GetAllKey = "#{Namespace}/get_all".freeze
|
13
14
|
|
14
15
|
# Private
|
15
16
|
def self.key_for(key)
|
@@ -32,9 +33,7 @@ module Flipper
|
|
32
33
|
|
33
34
|
# Public
|
34
35
|
def features
|
35
|
-
|
36
|
-
@adapter.features
|
37
|
-
end
|
36
|
+
read_feature_keys
|
38
37
|
end
|
39
38
|
|
40
39
|
# Public
|
@@ -67,20 +66,22 @@ module Flipper
|
|
67
66
|
end
|
68
67
|
|
69
68
|
def get_multi(features)
|
70
|
-
|
71
|
-
|
72
|
-
uncached_features = features.reject do |feature|
|
73
|
-
result[feature.key]
|
74
|
-
end
|
69
|
+
read_many_features(features)
|
70
|
+
end
|
75
71
|
|
76
|
-
|
77
|
-
|
72
|
+
def get_all
|
73
|
+
if @cache.setnx(GetAllKey, Time.now.to_i)
|
74
|
+
@cache.expire(GetAllKey, @ttl)
|
75
|
+
response = @adapter.get_all
|
78
76
|
response.each do |key, value|
|
79
|
-
set_with_ttl
|
80
|
-
result[key] = value
|
77
|
+
set_with_ttl key_for(key), value
|
81
78
|
end
|
79
|
+
set_with_ttl FeaturesKey, response.keys.to_set
|
80
|
+
response
|
81
|
+
else
|
82
|
+
features = read_feature_keys.map { |key| Flipper::Feature.new(key, self) }
|
83
|
+
read_many_features(features)
|
82
84
|
end
|
83
|
-
result
|
84
85
|
end
|
85
86
|
|
86
87
|
# Public
|
@@ -103,13 +104,37 @@ module Flipper
|
|
103
104
|
self.class.key_for(key)
|
104
105
|
end
|
105
106
|
|
107
|
+
def read_feature_keys
|
108
|
+
fetch(FeaturesKey) { @adapter.features }
|
109
|
+
end
|
110
|
+
|
111
|
+
def read_many_features(features)
|
112
|
+
keys = features.map(&:key)
|
113
|
+
cache_result = Hash[keys.zip(multi_cache_get(keys))]
|
114
|
+
uncached_features = features.reject { |feature| cache_result[feature.key] }
|
115
|
+
|
116
|
+
if uncached_features.any?
|
117
|
+
response = @adapter.get_multi(uncached_features)
|
118
|
+
response.each do |key, value|
|
119
|
+
set_with_ttl(key_for(key), value)
|
120
|
+
cache_result[key] = value
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
result = {}
|
125
|
+
features.each do |feature|
|
126
|
+
result[feature.key] = cache_result[feature.key]
|
127
|
+
end
|
128
|
+
result
|
129
|
+
end
|
130
|
+
|
106
131
|
def fetch(key)
|
107
132
|
cached = @cache.get(key)
|
108
133
|
if cached
|
109
134
|
Marshal.load(cached)
|
110
135
|
else
|
111
136
|
to_cache = yield
|
112
|
-
set_with_ttl(key, to_cache)
|
137
|
+
set_with_ttl(key_for(key), to_cache)
|
113
138
|
to_cache
|
114
139
|
end
|
115
140
|
end
|
data/lib/flipper/version.rb
CHANGED
@@ -1,20 +1,20 @@
|
|
1
1
|
require 'helper'
|
2
2
|
require 'flipper/adapters/memory'
|
3
|
+
require 'flipper/adapters/operation_logger'
|
3
4
|
require 'flipper/adapters/redis_cache'
|
4
5
|
require 'flipper/spec/shared_adapter_specs'
|
5
6
|
|
6
7
|
RSpec.describe Flipper::Adapters::RedisCache do
|
7
8
|
let(:client) do
|
8
9
|
options = {}
|
9
|
-
|
10
10
|
options[:url] = ENV['REDIS_URL'] if ENV['REDIS_URL']
|
11
|
-
|
12
11
|
Redis.new(options)
|
13
12
|
end
|
14
13
|
|
15
|
-
let(:memory_adapter)
|
16
|
-
|
17
|
-
|
14
|
+
let(:memory_adapter) do
|
15
|
+
Flipper::Adapters::OperationLogger.new(Flipper::Adapters::Memory.new)
|
16
|
+
end
|
17
|
+
let(:adapter) { described_class.new(memory_adapter, client) }
|
18
18
|
let(:flipper) { Flipper.new(adapter) }
|
19
19
|
|
20
20
|
subject { adapter }
|
@@ -30,7 +30,7 @@ RSpec.describe Flipper::Adapters::RedisCache do
|
|
30
30
|
feature = flipper[:stats]
|
31
31
|
adapter.get(feature)
|
32
32
|
adapter.remove(feature)
|
33
|
-
expect(
|
33
|
+
expect(client.get(described_class.key_for(feature))).to be(nil)
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
@@ -42,17 +42,50 @@ RSpec.describe Flipper::Adapters::RedisCache do
|
|
42
42
|
stats.enable
|
43
43
|
search.enable
|
44
44
|
|
45
|
+
memory_adapter.reset
|
46
|
+
|
45
47
|
adapter.get(stats)
|
46
|
-
expect(
|
47
|
-
expect(
|
48
|
+
expect(client.get(described_class.key_for(search))).to be(nil)
|
49
|
+
expect(client.get(described_class.key_for(other))).to be(nil)
|
48
50
|
|
49
51
|
adapter.get_multi([stats, search, other])
|
50
52
|
|
51
53
|
search_cache_value, other_cache_value = [search, other].map do |f|
|
52
|
-
Marshal.load(
|
54
|
+
Marshal.load(client.get(described_class.key_for(f)))
|
53
55
|
end
|
54
56
|
expect(search_cache_value[:boolean]).to eq('true')
|
55
57
|
expect(other_cache_value[:boolean]).to be(nil)
|
58
|
+
|
59
|
+
adapter.get_multi([stats, search, other])
|
60
|
+
adapter.get_multi([stats, search, other])
|
61
|
+
expect(memory_adapter.count(:get_multi)).to eq(1)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe '#get_all' do
|
66
|
+
let(:stats) { flipper[:stats] }
|
67
|
+
let(:search) { flipper[:search] }
|
68
|
+
|
69
|
+
before do
|
70
|
+
stats.enable
|
71
|
+
search.add
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'warms all features' do
|
75
|
+
adapter.get_all
|
76
|
+
expect(Marshal.load(client.get(described_class.key_for(stats.key)))[:boolean]).to eq('true')
|
77
|
+
expect(Marshal.load(client.get(described_class.key_for(search.key)))[:boolean]).to be(nil)
|
78
|
+
expect(client.get(described_class::GetAllKey).to_i).to be_within(2).of(Time.now.to_i)
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'returns same result when already cached' do
|
82
|
+
expect(adapter.get_all).to eq(adapter.get_all)
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'only invokes one call to wrapped adapter' do
|
86
|
+
memory_adapter.reset
|
87
|
+
5.times { adapter.get_all }
|
88
|
+
expect(memory_adapter.count(:get_all)).to eq(1)
|
56
89
|
end
|
57
90
|
end
|
58
91
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flipper-redis
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.11.0.
|
4
|
+
version: 0.11.0.rc1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Nunemaker
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-11-04 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: 0.11.0.
|
19
|
+
version: 0.11.0.rc1
|
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: 0.11.0.
|
26
|
+
version: 0.11.0.rc1
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: redis
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|