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 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