flipper-redis 0.11.0.beta9 → 0.11.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8180f4e89f30f967b7cf80a8c78670a04011313d
4
- data.tar.gz: 5001f56e1acfe6194955e7c9a0e60981985f309c
3
+ metadata.gz: a5f75cfdfc5971f034dc0769596d86a430a06020
4
+ data.tar.gz: 165e82e9aa9662d4562e693c09669bb1a1d0e7d9
5
5
  SHA512:
6
- metadata.gz: 1818e56084ef172bb54dde7ac7655216a5530a7e62957bd8b3a69c274b45e2314e7ab51ed473aab22aac16c3aab77e4fc33506111b1fb5394489900aed4d8faa
7
- data.tar.gz: 8890a3ca4abe1f48f1b1931afb6b869660770ead43feb2d11da4b3d46616da2d0b80b1ddefbfcb8e95b3e467a718c31b088f28163780e0a8c105d5900ff473f0
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
- @client.smembers(FeaturesKey).to_set
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
- docs = docs_for(features)
60
- result = {}
61
- features.zip(docs) do |feature, doc|
62
- result[feature.key] = result_for_feature(feature, doc)
63
- end
64
- result
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
- fetch(FeaturesKey) do
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
- keys = features.map(&:key)
71
- result = Hash[keys.zip(multi_cache_get(keys))]
72
- uncached_features = features.reject do |feature|
73
- result[feature.key]
74
- end
69
+ read_many_features(features)
70
+ end
75
71
 
76
- if uncached_features.any?
77
- response = @adapter.get_multi(uncached_features)
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(key_for(key), value)
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
@@ -1,3 +1,3 @@
1
1
  module Flipper
2
- VERSION = '0.11.0.beta9'.freeze
2
+ VERSION = '0.11.0.rc1'.freeze
3
3
  end
@@ -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) { Flipper::Adapters::Memory.new }
16
- let(:cache) { Redis.new(url: ENV.fetch('REDIS_URL', 'redis://localhost:6379')) }
17
- let(:adapter) { described_class.new(memory_adapter, cache) }
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(cache.get(described_class.key_for(feature))).to be(nil)
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(cache.get(described_class.key_for(search))).to be(nil)
47
- expect(cache.get(described_class.key_for(other))).to be(nil)
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(cache.get(described_class.key_for(f)))
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.beta9
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-10-28 00:00:00.000000000 Z
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.beta9
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.beta9
26
+ version: 0.11.0.rc1
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: redis
29
29
  requirement: !ruby/object:Gem::Requirement