flipper-redis 1.3.2 → 1.3.3

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: bea3fee40316abcb1c8f5456ac56e11e4c0335ac61d7c97a61ee2da019db1788
4
- data.tar.gz: ba0f54b8675619045d6bf4d81b411f06989355d3da183b7269b2ba250d335f28
3
+ metadata.gz: a790000c8a290b42d4e92173ddc5e00632c7113b16ca47c4c257d26ee36005aa
4
+ data.tar.gz: 6e6b7c2d513a8472e6bdc7cb99dff07daaf984751d7c7880bde92622663f95dc
5
5
  SHA512:
6
- metadata.gz: 647d41d33a87aa7bfe4e48a39b385d3a88f1a04aab357b768f6f1fac07eaf49b3502910c86dded0db5b02c63a72169b7239382af7b70ff2c4611865fa7a59ca8
7
- data.tar.gz: 50ef503e56b12b349caede24733e39ee66613c770f7f0a52565c75341535df6180e1af7359c5fdd0f8d0572a3ca644fa282fc1832730a87fd7f5eeb1008b278a
6
+ metadata.gz: ae7bf6f058f1a54ef97bbc2b3e86e03398d01c65df8f9752c5b0351d476e70d91754680df9223b15162c0dbd9c8cdfeb7ce5f4d40da6c6443915a2c8cecaf777
7
+ data.tar.gz: 709339de3e5a6cb919a2ae8fbf63f882f16fc06b7339b4fe171aef7d70feb4961031af6269b6fede7877a0bd5d1b96962b3025cc2bd4285ea6abe87ee0d59cc4
@@ -1,11 +1,13 @@
1
1
  require 'set'
2
2
  require 'redis'
3
3
  require 'flipper'
4
+ require 'flipper/adapters/redis_shared/methods'
4
5
 
5
6
  module Flipper
6
7
  module Adapters
7
8
  class Redis
8
9
  include ::Flipper::Adapter
10
+ include ::Flipper::Adapters::RedisShared
9
11
 
10
12
  attr_reader :key_prefix
11
13
 
@@ -25,6 +27,9 @@ module Flipper
25
27
  def initialize(client, key_prefix: nil)
26
28
  @client = client
27
29
  @key_prefix = key_prefix
30
+ @sadd_returns_boolean = with_connection do |conn|
31
+ conn.class.respond_to?(:sadd_returns_boolean) && conn.class.sadd_returns_boolean
32
+ end
28
33
  end
29
34
 
30
35
  # Public: The set of known features.
@@ -35,9 +40,9 @@ module Flipper
35
40
  # Public: Adds a feature to the set of known features.
36
41
  def add(feature)
37
42
  if redis_sadd_returns_boolean?
38
- @client.sadd? features_key, feature.key
43
+ with_connection { |conn| conn.sadd? features_key, feature.key }
39
44
  else
40
- @client.sadd features_key, feature.key
45
+ with_connection { |conn| conn.sadd features_key, feature.key }
41
46
  end
42
47
  true
43
48
  end
@@ -45,17 +50,17 @@ module Flipper
45
50
  # Public: Removes a feature from the set of known features.
46
51
  def remove(feature)
47
52
  if redis_sadd_returns_boolean?
48
- @client.srem? features_key, feature.key
53
+ with_connection { |conn| conn.srem? features_key, feature.key }
49
54
  else
50
- @client.srem features_key, feature.key
55
+ with_connection { |conn| conn.srem features_key, feature.key }
51
56
  end
52
- @client.del key_for(feature.key)
57
+ with_connection { |conn| conn.del key_for(feature.key) }
53
58
  true
54
59
  end
55
60
 
56
61
  # Public: Clears the gate values for a feature.
57
62
  def clear(feature)
58
- @client.del key_for(feature.key)
63
+ with_connection { |conn| conn.del key_for(feature.key) }
59
64
  true
60
65
  end
61
66
 
@@ -88,13 +93,13 @@ module Flipper
88
93
  case gate.data_type
89
94
  when :boolean
90
95
  clear(feature)
91
- @client.hset feature_key, gate.key, thing.value.to_s
96
+ with_connection { |conn| conn.hset feature_key, gate.key, thing.value.to_s }
92
97
  when :integer
93
- @client.hset feature_key, gate.key, thing.value.to_s
98
+ with_connection { |conn| conn.hset feature_key, gate.key, thing.value.to_s }
94
99
  when :set
95
- @client.hset feature_key, to_field(gate, thing), 1
100
+ with_connection { |conn| conn.hset feature_key, to_field(gate, thing), 1 }
96
101
  when :json
97
- @client.hset feature_key, gate.key, Typecast.to_json(thing.value)
102
+ with_connection { |conn| conn.hset feature_key, gate.key, Typecast.to_json(thing.value) }
98
103
  else
99
104
  unsupported_data_type gate.data_type
100
105
  end
@@ -113,13 +118,13 @@ module Flipper
113
118
  feature_key = key_for(feature.key)
114
119
  case gate.data_type
115
120
  when :boolean
116
- @client.del feature_key
121
+ with_connection { |conn| conn.del feature_key }
117
122
  when :integer
118
- @client.hset feature_key, gate.key, thing.value.to_s
123
+ with_connection { |conn| conn.hset feature_key, gate.key, thing.value.to_s }
119
124
  when :set
120
- @client.hdel feature_key, to_field(gate, thing)
125
+ with_connection { |conn| conn.hdel feature_key, to_field(gate, thing) }
121
126
  when :json
122
- @client.hdel feature_key, gate.key
127
+ with_connection { |conn| conn.hdel feature_key, gate.key }
123
128
  else
124
129
  unsupported_data_type gate.data_type
125
130
  end
@@ -130,7 +135,7 @@ module Flipper
130
135
  private
131
136
 
132
137
  def redis_sadd_returns_boolean?
133
- @client.class.respond_to?(:sadd_returns_boolean) && @client.class.sadd_returns_boolean
138
+ @sadd_returns_boolean
134
139
  end
135
140
 
136
141
  def read_many_features(features)
@@ -143,20 +148,26 @@ module Flipper
143
148
  end
144
149
 
145
150
  def read_feature_keys
146
- @client.smembers(features_key).to_set
151
+ with_connection { |conn| conn.smembers(features_key).to_set }
147
152
  end
148
153
 
149
154
  # Private: Gets a hash of fields => values for the given feature.
150
155
  #
151
156
  # Returns a Hash of fields => values.
152
- def doc_for(feature, pipeline: @client)
153
- pipeline.hgetall(key_for(feature.key))
157
+ def doc_for(feature, pipeline: nil)
158
+ if pipeline
159
+ pipeline.hgetall(key_for(feature.key))
160
+ else
161
+ with_connection { |conn| conn.hgetall(key_for(feature.key)) }
162
+ end
154
163
  end
155
164
 
156
165
  def docs_for(features)
157
- @client.pipelined do |pipeline|
158
- features.each do |feature|
159
- doc_for(feature, pipeline: pipeline)
166
+ with_connection do |conn|
167
+ conn.pipelined do |pipeline|
168
+ features.each do |feature|
169
+ doc_for(feature, pipeline: pipeline)
170
+ end
160
171
  end
161
172
  end
162
173
  end
@@ -208,7 +219,7 @@ end
208
219
 
209
220
  Flipper.configure do |config|
210
221
  config.adapter do
211
- client = Redis.new(url: ENV["FLIPPER_REDIS_URL"] || ENV["REDIS_URL"])
222
+ client = Redis.new(url: ENV["FLIPPER_REDIS_URL"] || ENV["REDIS_URL"] || "redis://localhost:6379")
212
223
  Flipper::Adapters::Redis.new(client)
213
224
  end
214
225
  end
@@ -1,20 +1,24 @@
1
1
  require 'redis'
2
2
  require 'flipper'
3
3
  require 'flipper/adapters/cache_base'
4
+ require 'flipper/adapters/redis_shared/methods'
4
5
 
5
6
  module Flipper
6
7
  module Adapters
7
8
  # Public: Adapter that wraps another adapter with the ability to cache
8
9
  # adapter calls in Redis.
9
10
  class RedisCache < CacheBase
11
+ include ::Flipper::Adapters::RedisShared
12
+
10
13
  def initialize(adapter, cache, ttl = 3600, prefix: nil)
14
+ @client = cache
11
15
  super
12
16
  end
13
17
 
14
18
  private
15
19
 
16
20
  def cache_fetch(key, &block)
17
- cached = @cache.get(key)
21
+ cached = with_connection { |conn| conn.get(key) }
18
22
  if cached
19
23
  Marshal.load(cached)
20
24
  else
@@ -27,7 +31,7 @@ module Flipper
27
31
  def cache_read_multi(keys)
28
32
  return {} if keys.empty?
29
33
 
30
- values = @cache.mget(*keys).map do |value|
34
+ values = with_connection { |conn| conn.mget(*keys) }.map do |value|
31
35
  value ? Marshal.load(value) : nil
32
36
  end
33
37
 
@@ -35,11 +39,11 @@ module Flipper
35
39
  end
36
40
 
37
41
  def cache_write(key, value)
38
- @cache.setex(key, @ttl, Marshal.dump(value))
42
+ with_connection { |conn| conn.setex(key, @ttl, Marshal.dump(value)) }
39
43
  end
40
44
 
41
45
  def cache_delete(key)
42
- @cache.del(key)
46
+ with_connection { |conn| conn.del(key) }
43
47
  end
44
48
  end
45
49
  end
@@ -0,0 +1,9 @@
1
+ module Flipper
2
+ module Adapters
3
+ module RedisShared
4
+ def with_connection(&block)
5
+ @client.respond_to?(:with) ? @client.with(&block) : yield(@client)
6
+ end
7
+ end
8
+ end
9
+ end
@@ -1,5 +1,5 @@
1
1
  module Flipper
2
- VERSION = '1.3.2'.freeze
2
+ VERSION = '1.3.3'.freeze
3
3
 
4
4
  REQUIRED_RUBY_VERSION = '2.6'.freeze
5
5
  NEXT_REQUIRED_RUBY_VERSION = '3.0'.freeze
@@ -3,9 +3,7 @@ require 'flipper/adapters/redis_cache'
3
3
 
4
4
  RSpec.describe Flipper::Adapters::RedisCache do
5
5
  let(:client) do
6
- options = {}
7
- options[:url] = ENV['REDIS_URL'] if ENV['REDIS_URL']
8
- Redis.new(options)
6
+ Redis.new(url: ENV.fetch('REDIS_URL', 'redis://localhost:6379'))
9
7
  end
10
8
 
11
9
  let(:memory_adapter) do
@@ -1,55 +1,101 @@
1
1
  require 'flipper/adapters/redis'
2
+ require 'connection_pool'
2
3
 
3
4
  RSpec.describe Flipper::Adapters::Redis do
4
- let(:client) do
5
- options = {}
5
+ context "redis instance" do
6
+ let(:client) do
7
+ Redis.raise_deprecations = true
8
+ Redis.new(url: ENV.fetch('REDIS_URL', 'redis://localhost:6379'))
9
+ end
6
10
 
7
- options[:url] = ENV['REDIS_URL'] if ENV['REDIS_URL']
11
+ subject { described_class.new(client) }
8
12
 
9
- Redis.raise_deprecations = true
10
- Redis.new(options)
11
- end
13
+ before do
14
+ skip_on_error(Redis::CannotConnectError, 'Redis not available') do
15
+ client.flushdb
16
+ end
17
+ end
18
+
19
+ it_should_behave_like 'a flipper adapter'
12
20
 
13
- subject { described_class.new(client) }
21
+ it 'configures itself on load' do
22
+ Flipper.configuration = nil
23
+ Flipper.instance = nil
14
24
 
15
- before do
16
- skip_on_error(Redis::CannotConnectError, 'Redis not available') do
17
- client.flushdb
25
+ silence { load 'flipper/adapters/redis.rb' }
26
+
27
+ expect(Flipper.adapter.adapter).to be_a(Flipper::Adapters::Redis)
18
28
  end
19
- end
20
29
 
21
- it_should_behave_like 'a flipper adapter'
30
+ describe 'with a key_prefix' do
31
+ let(:subject) { described_class.new(client, key_prefix: "lockbox:") }
32
+ let(:feature) { Flipper::Feature.new(:search, subject) }
33
+
34
+ it_should_behave_like 'a flipper adapter'
35
+
36
+ it 'namespaces feature-keys' do
37
+ subject.add(feature)
22
38
 
23
- it 'configures itself on load' do
24
- Flipper.configuration = nil
25
- Flipper.instance = nil
39
+ expect(client.smembers("flipper_features")).to eq([])
40
+ expect(client.exists?("search")).to eq(false)
41
+ expect(client.smembers("lockbox:flipper_features")).to eq(["search"])
42
+ expect(client.hgetall("lockbox:search")).not_to eq(nil)
43
+ end
26
44
 
27
- silence { load 'flipper/adapters/redis.rb' }
45
+ it "can remove namespaced keys" do
46
+ subject.add(feature)
47
+ expect(client.smembers("lockbox:flipper_features")).to eq(["search"])
28
48
 
29
- expect(Flipper.adapter.adapter).to be_a(Flipper::Adapters::Redis)
49
+ subject.remove(feature)
50
+ expect(client.smembers("lockbox:flipper_features")).to be_empty
51
+ end
52
+ end
30
53
  end
31
54
 
32
- describe 'with a key_prefix' do
33
- let(:subject) { described_class.new(client, key_prefix: "lockbox:") }
34
- let(:feature) { Flipper::Feature.new(:search, subject) }
55
+ context "with a connection pool instance" do
56
+ let(:client) do
57
+ Redis.raise_deprecations = true
58
+ ConnectionPool.new(size: 1, timeout: 1) {
59
+ Redis.new(url: ENV.fetch('REDIS_URL', 'redis://localhost:6379'))
60
+ }
61
+ end
62
+
63
+ subject { described_class.new(client) }
64
+
65
+ before do
66
+ skip_on_error(Redis::CannotConnectError, 'Redis not available') do
67
+ client.with { |conn| conn.flushdb }
68
+ end
69
+ end
35
70
 
36
71
  it_should_behave_like 'a flipper adapter'
37
72
 
38
- it 'namespaces feature-keys' do
39
- subject.add(feature)
73
+ describe 'with a key_prefix' do
74
+ let(:subject) { described_class.new(client, key_prefix: "lockbox:") }
75
+ let(:feature) { Flipper::Feature.new(:search, subject) }
40
76
 
41
- expect(client.smembers("flipper_features")).to eq([])
42
- expect(client.exists?("search")).to eq(false)
43
- expect(client.smembers("lockbox:flipper_features")).to eq(["search"])
44
- expect(client.hgetall("lockbox:search")).not_to eq(nil)
45
- end
77
+ it_should_behave_like 'a flipper adapter'
78
+
79
+ it 'namespaces feature-keys' do
80
+ subject.add(feature)
81
+
82
+ client.with do |conn|
83
+ expect(conn.smembers("flipper_features")).to eq([])
84
+ expect(conn.exists?("search")).to eq(false)
85
+ expect(conn.smembers("lockbox:flipper_features")).to eq(["search"])
86
+ expect(conn.hgetall("lockbox:search")).not_to eq(nil)
87
+ end
88
+ end
46
89
 
47
- it "can remove namespaced keys" do
48
- subject.add(feature)
49
- expect(client.smembers("lockbox:flipper_features")).to eq(["search"])
90
+ it "can remove namespaced keys" do
91
+ client.with do |conn|
92
+ subject.add(feature)
93
+ expect(conn.smembers("lockbox:flipper_features")).to eq(["search"])
50
94
 
51
- subject.remove(feature)
52
- expect(client.smembers("lockbox:flipper_features")).to be_empty
95
+ subject.remove(feature)
96
+ expect(conn.smembers("lockbox:flipper_features")).to be_empty
97
+ end
98
+ end
53
99
  end
54
100
  end
55
101
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flipper-redis
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.2
4
+ version: 1.3.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Nunemaker
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2024-11-19 00:00:00.000000000 Z
10
+ date: 2025-02-24 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: flipper
@@ -16,14 +15,14 @@ dependencies:
16
15
  requirements:
17
16
  - - "~>"
18
17
  - !ruby/object:Gem::Version
19
- version: 1.3.2
18
+ version: 1.3.3
20
19
  type: :runtime
21
20
  prerelease: false
22
21
  version_requirements: !ruby/object:Gem::Requirement
23
22
  requirements:
24
23
  - - "~>"
25
24
  - !ruby/object:Gem::Version
26
- version: 1.3.2
25
+ version: 1.3.3
27
26
  - !ruby/object:Gem::Dependency
28
27
  name: redis
29
28
  requirement: !ruby/object:Gem::Requirement
@@ -44,7 +43,6 @@ dependencies:
44
43
  - - "<"
45
44
  - !ruby/object:Gem::Version
46
45
  version: '6'
47
- description:
48
46
  email: support@flippercloud.io
49
47
  executables: []
50
48
  extensions: []
@@ -57,6 +55,7 @@ files:
57
55
  - lib/flipper-redis.rb
58
56
  - lib/flipper/adapters/redis.rb
59
57
  - lib/flipper/adapters/redis_cache.rb
58
+ - lib/flipper/adapters/redis_shared/methods.rb
60
59
  - lib/flipper/version.rb
61
60
  - spec/flipper/adapters/redis_cache_spec.rb
62
61
  - spec/flipper/adapters/redis_spec.rb
@@ -70,8 +69,8 @@ metadata:
70
69
  homepage_uri: https://www.flippercloud.io
71
70
  source_code_uri: https://github.com/flippercloud/flipper
72
71
  bug_tracker_uri: https://github.com/flippercloud/flipper/issues
73
- changelog_uri: https://github.com/flippercloud/flipper/releases/tag/v1.3.2
74
- post_install_message:
72
+ changelog_uri: https://github.com/flippercloud/flipper/releases/tag/v1.3.3
73
+ funding_uri: https://github.com/sponsors/flippercloud
75
74
  rdoc_options: []
76
75
  require_paths:
77
76
  - lib
@@ -86,8 +85,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
86
85
  - !ruby/object:Gem::Version
87
86
  version: '0'
88
87
  requirements: []
89
- rubygems_version: 3.5.23
90
- signing_key:
88
+ rubygems_version: 3.6.5
91
89
  specification_version: 4
92
90
  summary: Redis feature flag adapter for Flipper
93
91
  test_files: