flipper-redis 0.10.2 → 0.11.0.beta1
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/flipper-redis.gemspec +11 -11
- data/lib/flipper/adapters/redis.rb +11 -10
- data/lib/flipper/adapters/redis_cache.rb +129 -0
- data/lib/flipper/version.rb +1 -1
- data/spec/flipper/adapters/redis_cache_spec.rb +64 -0
- data/spec/flipper/adapters/redis_spec.rb +3 -5
- data/test/adapters/redis_cache_test.rb +18 -0
- data/test/adapters/redis_test.rb +3 -2
- metadata +12 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fdeb25654096e05e254effadaec3e4172f5017a4
|
4
|
+
data.tar.gz: 3ce4cde5901b75e961137eddc00023e0d7ee6f5b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b5c985b97209b5b20cbe053da4c0c2fecdf40ab1f9287fdefc9094b198d3457e8f0464527a2b79098ada13f6eb5e07ec461eac2698c3a76529710f5bc81709ce
|
7
|
+
data.tar.gz: ec607bd967b5d16568b4507bca7b80d2d11937b8feaf4776a38258764202207d878c4e49d5901fbe61b688f4e6e40939ea651db2c49484068cd204b2afc1ff10
|
data/flipper-redis.gemspec
CHANGED
@@ -1,22 +1,22 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
require File.expand_path('../lib/flipper/version', __FILE__)
|
3
3
|
|
4
|
-
flipper_redis_files = lambda
|
4
|
+
flipper_redis_files = lambda do |file|
|
5
5
|
file =~ /redis/
|
6
|
-
|
6
|
+
end
|
7
7
|
|
8
8
|
Gem::Specification.new do |gem|
|
9
|
-
gem.authors = [
|
10
|
-
gem.email = [
|
11
|
-
gem.summary =
|
12
|
-
gem.description =
|
13
|
-
gem.license =
|
14
|
-
gem.homepage =
|
9
|
+
gem.authors = ['John Nunemaker']
|
10
|
+
gem.email = ['nunemaker@gmail.com']
|
11
|
+
gem.summary = 'Redis adapter for Flipper'
|
12
|
+
gem.description = 'Redis adapter for Flipper'
|
13
|
+
gem.license = 'MIT'
|
14
|
+
gem.homepage = 'https://github.com/jnunemaker/flipper'
|
15
15
|
|
16
|
-
gem.files = `git ls-files`.split("\n").select(&flipper_redis_files) + [
|
16
|
+
gem.files = `git ls-files`.split("\n").select(&flipper_redis_files) + ['lib/flipper/version.rb']
|
17
17
|
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n").select(&flipper_redis_files)
|
18
|
-
gem.name =
|
19
|
-
gem.require_paths = [
|
18
|
+
gem.name = 'flipper-redis'
|
19
|
+
gem.require_paths = ['lib']
|
20
20
|
gem.version = Flipper::VERSION
|
21
21
|
|
22
22
|
gem.add_dependency 'flipper', "~> #{Flipper::VERSION}"
|
@@ -68,7 +68,7 @@ module Flipper
|
|
68
68
|
#
|
69
69
|
# feature - The Flipper::Feature for the gate.
|
70
70
|
# gate - The Flipper::Gate to disable.
|
71
|
-
# thing - The Flipper::Type being
|
71
|
+
# thing - The Flipper::Type being enabled for the gate.
|
72
72
|
#
|
73
73
|
# Returns true.
|
74
74
|
def enable(feature, gate, thing)
|
@@ -126,14 +126,15 @@ module Flipper
|
|
126
126
|
fields = doc.keys
|
127
127
|
|
128
128
|
feature.gates.each do |gate|
|
129
|
-
result[gate.key] =
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
129
|
+
result[gate.key] =
|
130
|
+
case gate.data_type
|
131
|
+
when :boolean, :integer
|
132
|
+
doc[gate.key.to_s]
|
133
|
+
when :set
|
134
|
+
fields_to_gate_value fields, gate
|
135
|
+
else
|
136
|
+
unsupported_data_type gate.data_type
|
137
|
+
end
|
137
138
|
end
|
138
139
|
|
139
140
|
result
|
@@ -148,7 +149,7 @@ module Flipper
|
|
148
149
|
#
|
149
150
|
# Returns a Set of the values enabled for the gate.
|
150
151
|
def fields_to_gate_value(fields, gate)
|
151
|
-
regex =
|
152
|
+
regex = %r{^#{Regexp.escape(gate.key.to_s)}/}
|
152
153
|
keys = fields.grep(regex)
|
153
154
|
values = keys.map { |key| key.split('/', 2).last }
|
154
155
|
values.to_set
|
@@ -0,0 +1,129 @@
|
|
1
|
+
require 'redis'
|
2
|
+
|
3
|
+
module Flipper
|
4
|
+
module Adapters
|
5
|
+
# Public: Adapter that wraps another adapter with the ability to cache
|
6
|
+
# adapter calls in Redis
|
7
|
+
class RedisCache
|
8
|
+
include ::Flipper::Adapter
|
9
|
+
|
10
|
+
Version = 'v1'.freeze
|
11
|
+
Namespace = "flipper/#{Version}".freeze
|
12
|
+
FeaturesKey = "#{Namespace}/features".freeze
|
13
|
+
|
14
|
+
# Private
|
15
|
+
def self.key_for(key)
|
16
|
+
"#{Namespace}/feature/#{key}"
|
17
|
+
end
|
18
|
+
|
19
|
+
# Internal
|
20
|
+
attr_reader :cache
|
21
|
+
|
22
|
+
# Public: The name of the adapter.
|
23
|
+
attr_reader :name
|
24
|
+
|
25
|
+
# Public
|
26
|
+
def initialize(adapter, cache, ttl = 3600)
|
27
|
+
@adapter = adapter
|
28
|
+
@name = :redis_cache
|
29
|
+
@cache = cache
|
30
|
+
@ttl = ttl
|
31
|
+
end
|
32
|
+
|
33
|
+
# Public
|
34
|
+
def features
|
35
|
+
fetch(FeaturesKey) do
|
36
|
+
@adapter.features
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Public
|
41
|
+
def add(feature)
|
42
|
+
result = @adapter.add(feature)
|
43
|
+
@cache.del(FeaturesKey)
|
44
|
+
result
|
45
|
+
end
|
46
|
+
|
47
|
+
# Public
|
48
|
+
def remove(feature)
|
49
|
+
result = @adapter.remove(feature)
|
50
|
+
@cache.del(FeaturesKey)
|
51
|
+
@cache.del(key_for(feature.key))
|
52
|
+
result
|
53
|
+
end
|
54
|
+
|
55
|
+
# Public
|
56
|
+
def clear(feature)
|
57
|
+
result = @adapter.clear(feature)
|
58
|
+
@cache.del(key_for(feature.key))
|
59
|
+
result
|
60
|
+
end
|
61
|
+
|
62
|
+
# Public
|
63
|
+
def get(feature)
|
64
|
+
fetch(key_for(feature.key)) do
|
65
|
+
@adapter.get(feature)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
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
|
75
|
+
|
76
|
+
if uncached_features.any?
|
77
|
+
response = @adapter.get_multi(uncached_features)
|
78
|
+
response.each do |key, value|
|
79
|
+
set_with_ttl(key_for(key), value)
|
80
|
+
result[key] = value
|
81
|
+
end
|
82
|
+
end
|
83
|
+
result
|
84
|
+
end
|
85
|
+
|
86
|
+
# Public
|
87
|
+
def enable(feature, gate, thing)
|
88
|
+
result = @adapter.enable(feature, gate, thing)
|
89
|
+
@cache.del(key_for(feature.key))
|
90
|
+
result
|
91
|
+
end
|
92
|
+
|
93
|
+
# Public
|
94
|
+
def disable(feature, gate, thing)
|
95
|
+
result = @adapter.disable(feature, gate, thing)
|
96
|
+
@cache.del(key_for(feature.key))
|
97
|
+
result
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
|
102
|
+
def key_for(key)
|
103
|
+
self.class.key_for(key)
|
104
|
+
end
|
105
|
+
|
106
|
+
def fetch(key)
|
107
|
+
cached = @cache.get(key)
|
108
|
+
if cached
|
109
|
+
Marshal.load(cached)
|
110
|
+
else
|
111
|
+
to_cache = yield
|
112
|
+
set_with_ttl(key, to_cache)
|
113
|
+
to_cache
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def set_with_ttl(key, value)
|
118
|
+
@cache.setex(key, @ttl, Marshal.dump(value))
|
119
|
+
end
|
120
|
+
|
121
|
+
def multi_cache_get(keys)
|
122
|
+
cache_keys = keys.map { |key| key_for(key) }
|
123
|
+
@cache.mget(cache_keys).map do |value|
|
124
|
+
value ? Marshal.load(value) : nil
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
data/lib/flipper/version.rb
CHANGED
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'flipper/adapters/memory'
|
3
|
+
require 'flipper/adapters/redis_cache'
|
4
|
+
require 'flipper/spec/shared_adapter_specs'
|
5
|
+
|
6
|
+
RSpec.describe Flipper::Adapters::RedisCache do
|
7
|
+
let(:client) do
|
8
|
+
options = {}
|
9
|
+
|
10
|
+
options[:url] = ENV['BOXEN_REDIS_URL'] if ENV['BOXEN_REDIS_URL']
|
11
|
+
|
12
|
+
Redis.new(options)
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:memory_adapter) { Flipper::Adapters::Memory.new }
|
16
|
+
let(:cache) { Redis.new(url: ENV.fetch('BOXEN_REDIS_URL', 'redis://localhost:6379')) }
|
17
|
+
let(:adapter) { described_class.new(memory_adapter, cache) }
|
18
|
+
let(:flipper) { Flipper.new(adapter) }
|
19
|
+
|
20
|
+
subject { adapter }
|
21
|
+
|
22
|
+
before do
|
23
|
+
client.flushdb
|
24
|
+
end
|
25
|
+
|
26
|
+
it_should_behave_like 'a flipper adapter'
|
27
|
+
|
28
|
+
describe '#remove' do
|
29
|
+
it 'expires feature' do
|
30
|
+
feature = flipper[:stats]
|
31
|
+
adapter.get(feature)
|
32
|
+
adapter.remove(feature)
|
33
|
+
expect(cache.get(described_class.key_for(feature))).to be(nil)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe '#get_multi' do
|
38
|
+
it 'warms uncached features' do
|
39
|
+
stats = flipper[:stats]
|
40
|
+
search = flipper[:search]
|
41
|
+
other = flipper[:other]
|
42
|
+
stats.enable
|
43
|
+
search.enable
|
44
|
+
|
45
|
+
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
|
+
|
49
|
+
adapter.get_multi([stats, search, other])
|
50
|
+
|
51
|
+
search_cache_value, other_cache_value = [search, other].map do |f|
|
52
|
+
Marshal.load(cache.get(described_class.key_for(f)))
|
53
|
+
end
|
54
|
+
expect(search_cache_value[:boolean]).to eq('true')
|
55
|
+
expect(other_cache_value[:boolean]).to be(nil)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe '#name' do
|
60
|
+
it 'is redis_cache' do
|
61
|
+
expect(subject.name).to be(:redis_cache)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -3,15 +3,13 @@ require 'flipper/adapters/redis'
|
|
3
3
|
require 'flipper/spec/shared_adapter_specs'
|
4
4
|
|
5
5
|
RSpec.describe Flipper::Adapters::Redis do
|
6
|
-
let(:client)
|
6
|
+
let(:client) do
|
7
7
|
options = {}
|
8
8
|
|
9
|
-
if ENV['BOXEN_REDIS_URL']
|
10
|
-
options[:url] = ENV['BOXEN_REDIS_URL']
|
11
|
-
end
|
9
|
+
options[:url] = ENV['BOXEN_REDIS_URL'] if ENV['BOXEN_REDIS_URL']
|
12
10
|
|
13
11
|
Redis.new(options)
|
14
|
-
|
12
|
+
end
|
15
13
|
|
16
14
|
subject { described_class.new(client) }
|
17
15
|
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'flipper/adapters/memory'
|
3
|
+
require 'flipper/adapters/redis_cache'
|
4
|
+
|
5
|
+
class DalliTest < MiniTest::Test
|
6
|
+
prepend Flipper::Test::SharedAdapterTests
|
7
|
+
|
8
|
+
def setup
|
9
|
+
url = ENV.fetch('BOXEN_REDIS_URL', 'redis://localhost:6379')
|
10
|
+
@cache = Redis.new(url: url).tap(&:flushdb)
|
11
|
+
memory_adapter = Flipper::Adapters::Memory.new
|
12
|
+
@adapter = Flipper::Adapters::RedisCache.new(memory_adapter, @cache)
|
13
|
+
end
|
14
|
+
|
15
|
+
def teardown
|
16
|
+
@cache.flushdb
|
17
|
+
end
|
18
|
+
end
|
data/test/adapters/redis_test.rb
CHANGED
@@ -5,7 +5,8 @@ class RedisTest < MiniTest::Test
|
|
5
5
|
prepend Flipper::Test::SharedAdapterTests
|
6
6
|
|
7
7
|
def setup
|
8
|
-
|
9
|
-
|
8
|
+
url = ENV.fetch('BOXEN_REDIS_URL', 'redis://localhost:6379')
|
9
|
+
client = Redis.new(url: url).tap(&:flushdb)
|
10
|
+
@adapter = Flipper::Adapters::Redis.new(client)
|
10
11
|
end
|
11
12
|
end
|
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.
|
4
|
+
version: 0.11.0.beta1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Nunemaker
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-04-02 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.
|
19
|
+
version: 0.11.0.beta1
|
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.
|
26
|
+
version: 0.11.0.beta1
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: redis
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -58,8 +58,11 @@ files:
|
|
58
58
|
- flipper-redis.gemspec
|
59
59
|
- lib/flipper-redis.rb
|
60
60
|
- lib/flipper/adapters/redis.rb
|
61
|
+
- lib/flipper/adapters/redis_cache.rb
|
61
62
|
- lib/flipper/version.rb
|
63
|
+
- spec/flipper/adapters/redis_cache_spec.rb
|
62
64
|
- spec/flipper/adapters/redis_spec.rb
|
65
|
+
- test/adapters/redis_cache_test.rb
|
63
66
|
- test/adapters/redis_test.rb
|
64
67
|
homepage: https://github.com/jnunemaker/flipper
|
65
68
|
licenses:
|
@@ -76,15 +79,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
76
79
|
version: '0'
|
77
80
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
78
81
|
requirements:
|
79
|
-
- - "
|
82
|
+
- - ">"
|
80
83
|
- !ruby/object:Gem::Version
|
81
|
-
version:
|
84
|
+
version: 1.3.1
|
82
85
|
requirements: []
|
83
86
|
rubyforge_project:
|
84
|
-
rubygems_version: 2.
|
87
|
+
rubygems_version: 2.5.2
|
85
88
|
signing_key:
|
86
89
|
specification_version: 4
|
87
90
|
summary: Redis adapter for Flipper
|
88
91
|
test_files:
|
92
|
+
- spec/flipper/adapters/redis_cache_spec.rb
|
89
93
|
- spec/flipper/adapters/redis_spec.rb
|
94
|
+
- test/adapters/redis_cache_test.rb
|
90
95
|
- test/adapters/redis_test.rb
|