redis-store 1.5.0 → 1.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,8 +5,16 @@ class Redis
5
5
  super(key)
6
6
  end
7
7
 
8
+ REDIS_SET_OPTIONS = %i(ex px nx xx keepttl).freeze
9
+ private_constant :REDIS_SET_OPTIONS
10
+
8
11
  def set(key, value, options = nil)
9
- super(key, value, options || {})
12
+ if options && REDIS_SET_OPTIONS.any? { |k| options.key?(k) }
13
+ kwargs = REDIS_SET_OPTIONS.each_with_object({}) { |key, h| h[key] = options[key] if options.key?(key) }
14
+ super(key, value, **kwargs)
15
+ else
16
+ super(key, value)
17
+ end
10
18
  end
11
19
 
12
20
  def setnx(key, value, options = nil)
@@ -3,28 +3,32 @@ class Redis
3
3
  module Namespace
4
4
  FLUSHDB_BATCH_SIZE = 1000
5
5
 
6
- def set(key, val, options = nil)
7
- namespace(key) { |k| super(k, val, options) }
6
+ def set(key, *args)
7
+ namespace(key) { |k| super(k, *args) }
8
8
  end
9
9
 
10
- def setex(key, ttl, val, options = nil)
11
- namespace(key) { |k| super(k, ttl, val, options) }
10
+ def setex(key, *args)
11
+ namespace(key) { |k| super(k, *args) }
12
12
  end
13
13
 
14
- def setnx(key, val, options = nil)
15
- namespace(key) { |k| super(k, val, options) }
14
+ def setnx(key, *args)
15
+ namespace(key) { |k| super(k, *args) }
16
16
  end
17
17
 
18
18
  def ttl(key, options = nil)
19
19
  namespace(key) { |k| super(k) }
20
20
  end
21
21
 
22
- def get(key, options = nil)
23
- namespace(key) { |k| super(k, options) }
22
+ def get(key, *args)
23
+ namespace(key) { |k| super(k, *args) }
24
24
  end
25
25
 
26
- def exists(key)
27
- namespace(key) { |k| super(k) }
26
+ def exists(*keys)
27
+ super(*keys.map { |key| interpolate(key) })
28
+ end
29
+
30
+ def exists?(*keys)
31
+ super(*keys.map { |key| interpolate(key) })
28
32
  end
29
33
 
30
34
  def incrby(key, increment)
@@ -36,15 +40,30 @@ class Redis
36
40
  end
37
41
 
38
42
  def keys(pattern = "*")
39
- namespace(pattern) { |p| super(p).map{|key| strip_namespace(key) } }
43
+ namespace(pattern) { |p| super(p).map { |key| strip_namespace(key) } }
44
+ end
45
+
46
+ def scan(cursor, match: nil, **kwargs)
47
+ if match
48
+ namespace(match) do |pattern|
49
+ cursor, keys = super(cursor, match: pattern, **kwargs)
50
+ [ cursor, keys.map{ |key| strip_namespace(key) } ]
51
+ end
52
+ else
53
+ super(cursor, **kwargs)
54
+ end
40
55
  end
41
56
 
42
57
  def del(*keys)
43
- super(*keys.map {|key| interpolate(key) }) if keys.any?
58
+ super(*keys.map { |key| interpolate(key) }) if keys.any?
59
+ end
60
+
61
+ def unlink(*keys)
62
+ super(*keys.map { |key| interpolate(key) }) if keys.any?
44
63
  end
45
64
 
46
65
  def watch(*keys)
47
- super(*keys.map {|key| interpolate(key) }) if keys.any?
66
+ super(*keys.map { |key| interpolate(key) }) if keys.any?
48
67
  end
49
68
 
50
69
  def mget(*keys, &blk)
@@ -52,15 +71,95 @@ class Redis
52
71
  if keys.any?
53
72
  # Serialization gets extended before Namespace does, so we need to pass options further
54
73
  if singleton_class.ancestors.include? Serialization
55
- super(*keys.map {|key| interpolate(key) }, options, &blk)
74
+ super(*keys.map { |key| interpolate(key) }, options, &blk)
56
75
  else
57
- super(*keys.map {|key| interpolate(key) }, &blk)
76
+ super(*keys.map { |key| interpolate(key) }, &blk)
58
77
  end
59
78
  end
60
79
  end
61
80
 
62
81
  def expire(key, ttl)
63
- namespace(key) { |k| super(k, ttl) }
82
+ namespace(key) { |k| super(k, ttl) }
83
+ end
84
+
85
+ def hdel(key, *fields)
86
+ namespace(key) { |k| super(k, *fields) }
87
+ end
88
+
89
+ def hget(key, field)
90
+ namespace(key) { |k| super(k, field) }
91
+ end
92
+
93
+ def hgetall(key)
94
+ namespace(key) { |k| super(k) }
95
+ end
96
+
97
+ def hexists(key, field)
98
+ namespace(key) { |k| super(k, field) }
99
+ end
100
+
101
+ def hincrby(key, field, increment)
102
+ namespace(key) { |k| super(k, field, increment) }
103
+ end
104
+
105
+ def hincrbyfloat(key, field, increment)
106
+ namespace(key) { |k| super(k, field, increment) }
107
+ end
108
+
109
+ def hkeys(key)
110
+ namespace(key) { |k| super(k) }
111
+ end
112
+
113
+ def hlen(key)
114
+ namespace(key) { |k| super(k) }
115
+ end
116
+
117
+ def hmget(key, *fields, &blk)
118
+ namespace(key) { |k| super(k, *fields, &blk) }
119
+ end
120
+
121
+ def hmset(key, *attrs)
122
+ namespace(key) { |k| super(k, *attrs) }
123
+ end
124
+
125
+ def hset(key, *args)
126
+ namespace(key) { |k| super(k, *args) }
127
+ end
128
+
129
+ def hsetnx(key, field, val)
130
+ namespace(key) { |k| super(k, field, val) }
131
+ end
132
+
133
+ def hvals(key)
134
+ namespace(key) { |k| super(k) }
135
+ end
136
+
137
+ def hscan(key, *args)
138
+ namespace(key) { |k| super(k, *args) }
139
+ end
140
+
141
+ def hscan_each(key, *args)
142
+ namespace(key) { |k| super(k, *args) }
143
+ end
144
+
145
+ def zincrby(key, increment, member)
146
+ namespace(key) { |k| super(k, increment, member) }
147
+ end
148
+
149
+ def zscore(key, member)
150
+ namespace(key) { |k| super(k, member) }
151
+ end
152
+
153
+ def zadd(key, *args)
154
+ namespace(key) { |k| super(k, *args) }
155
+ end
156
+
157
+ def zrem(key, member)
158
+ namespace(key) { |k| super(k, member) }
159
+ end
160
+
161
+ if respond_to?(:ruby2_keywords, true)
162
+ ruby2_keywords :set, :setex, :setnx, :hscan, :hscan_each
64
163
  end
65
164
 
66
165
  def to_s
@@ -11,4 +11,3 @@ class Redis
11
11
  end
12
12
  end
13
13
  end
14
-
@@ -34,7 +34,7 @@ class Redis
34
34
  end
35
35
 
36
36
  def with_multi_or_pipelined(options, &block)
37
- return pipelined(&block) if options[:avoid_multi_commands]
37
+ return pipelined(&block) if options.key?(:cluster) || options[:avoid_multi_commands]
38
38
  multi(&block)
39
39
  end
40
40
  end
@@ -1,5 +1,5 @@
1
1
  class Redis
2
2
  class Store < self
3
- VERSION = '1.5.0'
3
+ VERSION = '1.9.0'
4
4
  end
5
5
  end
@@ -1,4 +1,5 @@
1
1
  # -*- encoding: utf-8 -*-
2
+
2
3
  $:.push File.expand_path('../lib', __FILE__)
3
4
  require 'redis/store/version'
4
5
 
@@ -8,21 +9,19 @@ Gem::Specification.new do |s|
8
9
  s.authors = ['Luca Guidi']
9
10
  s.email = ['me@lucaguidi.com']
10
11
  s.homepage = 'http://redis-store.org/redis-store'
11
- s.summary = %q{Redis stores for Ruby frameworks}
12
- s.description = %q{Namespaced Rack::Session, Rack::Cache, I18n and cache Redis stores for Ruby web frameworks.}
13
-
14
- s.rubyforge_project = 'redis-store'
12
+ s.summary = 'Redis stores for Ruby frameworks'
13
+ s.description = 'Namespaced Rack::Session, Rack::Cache, I18n and cache Redis stores for Ruby web frameworks.'
15
14
 
16
15
  s.files = `git ls-files`.split("\n")
17
16
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
19
18
  s.require_paths = ["lib"]
20
19
  s.license = 'MIT'
21
20
 
22
- s.add_dependency 'redis', '>= 2.2', '< 5'
21
+ s.add_dependency 'redis', '>= 4', '< 5'
23
22
 
24
- s.add_development_dependency 'rake', '~> 10'
25
- s.add_development_dependency 'bundler', '~> 1.3'
23
+ s.add_development_dependency 'rake', '>= 12.3.3'
24
+ s.add_development_dependency 'bundler'
26
25
  s.add_development_dependency 'mocha', '~> 0.14.0'
27
26
  s.add_development_dependency 'minitest', '~> 5'
28
27
  s.add_development_dependency 'git', '~> 1.2'
@@ -30,4 +29,5 @@ Gem::Specification.new do |s|
30
29
  s.add_development_dependency 'pry', '~> 0.10.4'
31
30
  s.add_development_dependency 'redis-store-testing'
32
31
  s.add_development_dependency 'appraisal', '~> 2.0'
32
+ s.add_development_dependency 'rubocop', '~> 0.54'
33
33
  end
@@ -3,8 +3,8 @@ require 'test_helper'
3
3
  describe "Redis::DistributedStore" do
4
4
  def setup
5
5
  @dmr = Redis::DistributedStore.new [
6
- {:host => "localhost", :port => "6380", :db => 0},
7
- {:host => "localhost", :port => "6381", :db => 0}
6
+ { :host => "localhost", :port => "6380", :db => 0 },
7
+ { :host => "localhost", :port => "6381", :db => 0 }
8
8
  ]
9
9
  @rabbit = OpenStruct.new :name => "bunny"
10
10
  @white_rabbit = OpenStruct.new :color => "white"
@@ -67,8 +67,8 @@ describe "Redis::DistributedStore" do
67
67
 
68
68
  it "passes through ring replica options" do
69
69
  dmr = Redis::DistributedStore.new [
70
- {:host => "localhost", :port => "6380", :db => 0},
71
- {:host => "localhost", :port => "6381", :db => 0}
70
+ { :host => "localhost", :port => "6380", :db => 0 },
71
+ { :host => "localhost", :port => "6381", :db => 0 }
72
72
  ], replicas: 1024
73
73
  dmr.ring.replicas.must_equal 1024
74
74
  end
@@ -76,8 +76,8 @@ describe "Redis::DistributedStore" do
76
76
  it "uses a custom ring object" do
77
77
  my_ring = Redis::HashRing.new
78
78
  dmr = Redis::DistributedStore.new [
79
- {:host => "localhost", :port => "6380", :db => 0},
80
- {:host => "localhost", :port => "6381", :db => 0}
79
+ { :host => "localhost", :port => "6380", :db => 0 },
80
+ { :host => "localhost", :port => "6381", :db => 0 }
81
81
  ], ring: my_ring
82
82
  dmr.ring.must_equal my_ring
83
83
  dmr.ring.nodes.length.must_equal 2
@@ -100,8 +100,8 @@ describe "Redis::DistributedStore" do
100
100
  describe "namespace" do
101
101
  it "uses namespaced key" do
102
102
  @dmr = Redis::DistributedStore.new [
103
- {:host => "localhost", :port => "6380", :db => 0},
104
- {:host => "localhost", :port => "6381", :db => 0}
103
+ { :host => "localhost", :port => "6380", :db => 0 },
104
+ { :host => "localhost", :port => "6381", :db => 0 }
105
105
  ], :namespace => "theplaylist"
106
106
 
107
107
  @dmr.expects(:node_for).with("theplaylist:rabbit").returns(@dmr.nodes.first)
@@ -22,6 +22,11 @@ describe "Redis::Store::Factory" do
22
22
  store.to_s.must_equal("Redis Client connected to localhost:6380 against DB 0")
23
23
  end
24
24
 
25
+ it "uses specified scheme" do
26
+ store = Redis::Store::Factory.create :scheme => "rediss"
27
+ store.instance_variable_get(:@client).scheme.must_equal('rediss')
28
+ end
29
+
25
30
  it "uses specified path" do
26
31
  store = Redis::Store::Factory.create :path => "/var/run/redis.sock"
27
32
  store.to_s.must_equal("Redis Client connected to /var/run/redis.sock against DB 0")
@@ -69,6 +74,23 @@ describe "Redis::Store::Factory" do
69
74
  store.instance_variable_get(:@options)[:raw].must_equal(false)
70
75
  end
71
76
 
77
+ describe "defaults" do
78
+ it "defaults to localhost if no host specified" do
79
+ store = Redis::Store::Factory.create
80
+ store.instance_variable_get(:@client).host.must_equal('127.0.0.1')
81
+ end
82
+
83
+ it "defaults to 6379 if no port specified" do
84
+ store = Redis::Store::Factory.create
85
+ store.instance_variable_get(:@client).port.must_equal(6379)
86
+ end
87
+
88
+ it "defaults to redis:// if no scheme specified" do
89
+ store = Redis::Store::Factory.create
90
+ store.instance_variable_get(:@client).scheme.must_equal('redis')
91
+ end
92
+ end
93
+
72
94
  describe 'with stdout disabled' do
73
95
  before do
74
96
  @original_stderr = $stderr
@@ -98,11 +120,11 @@ describe "Redis::Store::Factory" do
98
120
 
99
121
  it "should instantiate a Redis::DistributedStore store" do
100
122
  store = Redis::Store::Factory.create(
101
- {:host => "localhost", :port => 6379},
102
- {:host => "localhost", :port => 6380}
123
+ { :host => "localhost", :port => 6379 },
124
+ { :host => "localhost", :port => 6380 }
103
125
  )
104
126
  store.must_be_kind_of(Redis::DistributedStore)
105
- store.nodes.map {|node| node.to_s }.must_equal([
127
+ store.nodes.map { |node| node.to_s }.must_equal([
106
128
  "Redis Client connected to localhost:6379 against DB 0",
107
129
  "Redis Client connected to localhost:6380 against DB 0",
108
130
  ])
@@ -120,6 +142,16 @@ describe "Redis::Store::Factory" do
120
142
  store.to_s.must_equal("Redis Client connected to 127.0.0.1:6380 against DB 0")
121
143
  end
122
144
 
145
+ it "uses specified scheme" do
146
+ store = Redis::Store::Factory.create "rediss://127.0.0.1:6380"
147
+ store.instance_variable_get(:@client).scheme.must_equal('rediss')
148
+ end
149
+
150
+ it "correctly defaults to redis:// when relative scheme specified" do
151
+ store = Redis::Store::Factory.create "//127.0.0.1:6379"
152
+ store.instance_variable_get(:@client).scheme.must_equal('redis')
153
+ end
154
+
123
155
  it "uses specified path" do
124
156
  store = Redis::Store::Factory.create "unix:///var/run/redis.sock"
125
157
  store.to_s.must_equal("Redis Client connected to /var/run/redis.sock against DB 0")
@@ -174,50 +206,50 @@ describe "Redis::Store::Factory" do
174
206
  it "instantiates Redis::DistributedStore" do
175
207
  store = Redis::Store::Factory.create "redis://127.0.0.1:6379", "redis://127.0.0.1:6380"
176
208
  store.must_be_kind_of(Redis::DistributedStore)
177
- store.nodes.map {|node| node.to_s }.must_equal([
209
+ store.nodes.map { |node| node.to_s }.must_equal([
178
210
  "Redis Client connected to 127.0.0.1:6379 against DB 0",
179
211
  "Redis Client connected to 127.0.0.1:6380 against DB 0",
180
212
  ])
181
213
  end
182
214
  end
183
215
 
184
- describe 'when given host Hash and options Hash' do
216
+ describe 'when given host Hash and options Hash' do
185
217
  it 'instantiates Redis::Store and merges options' do
186
218
  store = Redis::Store::Factory.create(
187
- { :host => '127.0.0.1', :port => '6379' },
219
+ { :host => '127.0.0.1', :port => '6379' },
188
220
  { :namespace => 'theplaylist' }
189
221
  )
190
222
  end
191
223
 
192
- it 'instantiates Redis::DistributedStore and merges options' do
224
+ it 'instantiates Redis::DistributedStore and merges options' do
193
225
  store = Redis::Store::Factory.create(
194
- { :host => '127.0.0.1', :port => '6379' },
195
- { :host => '127.0.0.1', :port => '6380' },
226
+ { :host => '127.0.0.1', :port => '6379' },
227
+ { :host => '127.0.0.1', :port => '6380' },
196
228
  { :namespace => 'theplaylist' }
197
229
  )
198
- store.nodes.map {|node| node.to_s }.must_equal([
230
+ store.nodes.map { |node| node.to_s }.must_equal([
199
231
  "Redis Client connected to 127.0.0.1:6379 against DB 0 with namespace theplaylist",
200
232
  "Redis Client connected to 127.0.0.1:6380 against DB 0 with namespace theplaylist"
201
233
  ])
202
234
  end
203
235
  end
204
236
 
205
- describe 'when given host String and options Hash' do
206
- it 'instantiates Redis::Store and merges options' do
207
- store = Redis::Store::Factory.create "redis://127.0.0.1", { :namespace => 'theplaylist' }
237
+ describe 'when given host String and options Hash' do
238
+ it 'instantiates Redis::Store and merges options' do
239
+ store = Redis::Store::Factory.create "redis://127.0.0.1", :namespace => 'theplaylist'
208
240
  store.to_s.must_equal("Redis Client connected to 127.0.0.1:6379 against DB 0 with namespace theplaylist")
209
241
  end
210
242
 
211
- it 'instantiates Redis::DistributedStore and merges options' do
212
- store = Redis::Store::Factory.create "redis://127.0.0.1:6379", "redis://127.0.0.1:6380", { :namespace => 'theplaylist' }
213
- store.nodes.map {|node| node.to_s }.must_equal([
243
+ it 'instantiates Redis::DistributedStore and merges options' do
244
+ store = Redis::Store::Factory.create "redis://127.0.0.1:6379", "redis://127.0.0.1:6380", :namespace => 'theplaylist'
245
+ store.nodes.map { |node| node.to_s }.must_equal([
214
246
  "Redis Client connected to 127.0.0.1:6379 against DB 0 with namespace theplaylist",
215
247
  "Redis Client connected to 127.0.0.1:6380 against DB 0 with namespace theplaylist",
216
248
  ])
217
249
  end
218
250
 
219
251
  it 'instantiates Redis::Store and sets namespace from String' do
220
- store = Redis::Store::Factory.create "redis://127.0.0.1:6379/0/theplaylist", { :expire_after => 5 }
252
+ store = Redis::Store::Factory.create "redis://127.0.0.1:6379/0/theplaylist", :expire_after => 5
221
253
  store.to_s.must_equal("Redis Client connected to 127.0.0.1:6379 against DB 0 with namespace theplaylist")
222
254
  end
223
255
  end
@@ -10,18 +10,18 @@ describe Redis::Store::Interface do
10
10
  end
11
11
 
12
12
  it "should get an element" do
13
- lambda { @r.get("key", :option => true) } #.wont_raise ArgumentError
13
+ lambda { @r.get("key", :option => true) } # .wont_raise ArgumentError
14
14
  end
15
15
 
16
16
  it "should set an element" do
17
- lambda { @r.set("key", "value", :option => true) } #.wont_raise ArgumentError
17
+ lambda { @r.set("key", "value", :option => true) } # .wont_raise ArgumentError
18
18
  end
19
19
 
20
20
  it "should setnx an element" do
21
- lambda { @r.setnx("key", "value", :option => true) } #.wont_raise ArgumentError
21
+ lambda { @r.setnx("key", "value", :option => true) } # .wont_raise ArgumentError
22
22
  end
23
23
 
24
24
  it "should setex an element" do
25
- lambda { @r.setex("key", 1, "value", :option => true) } #.wont_raise ArgumentError
25
+ lambda { @r.setex("key", 1, "value", :option => true) } # .wont_raise ArgumentError
26
26
  end
27
27
  end