redis-store 1.4.1 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +2 -0
- data/.travis.yml +20 -4
- data/Appraisals +8 -0
- data/CHANGELOG.md +18 -0
- data/Gemfile +5 -0
- data/Rakefile +8 -0
- data/gemfiles/redis_3_x.gemfile +7 -0
- data/gemfiles/redis_4_x.gemfile +7 -0
- data/lib/redis/distributed_store.rb +5 -5
- data/lib/redis/store.rb +11 -2
- data/lib/redis/store/factory.rb +23 -17
- data/lib/redis/store/namespace.rb +4 -3
- data/lib/redis/store/serialization.rb +4 -3
- data/lib/redis/store/version.rb +1 -1
- data/redis-store.gemspec +1 -0
- data/test/redis/distributed_store_test.rb +44 -0
- data/test/redis/store/factory_test.rb +20 -0
- data/test/redis/store/namespace_test.rb +27 -2
- data/test/redis/store/serialization_test.rb +23 -12
- metadata +20 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 10e6007fb1a0708fe88d7627a23a2b5e8e0303e9ee81ec886d27a5c6fdb7ed07
|
4
|
+
data.tar.gz: 9415f933dae0284fe8114cf6d350561bc23c58bcf9f1182d734f36fdf8436707
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 69a4d72561bf0b9da2c88cc7a32d37a7ca06bb758a60d338bc4c12added10c1549f818f6e0e68af3854e0911a92f591c3c3094455d731f7a48d1cb1b47a9a700
|
7
|
+
data.tar.gz: da5fee4e7926a6032ca82fa7ee924c0a676124bffb55c84d5f553f066eb0ca47678cad583403ccc5979d04b7ddcdeb98652edf906472db364713baf483bc64e3
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -1,19 +1,35 @@
|
|
1
1
|
language: ruby
|
2
2
|
sudo: false
|
3
3
|
cache: bundler
|
4
|
+
notifications:
|
5
|
+
webhooks: https://www.travisbuddy.com
|
6
|
+
on_success: never
|
7
|
+
|
8
|
+
# 1.9.3 has Bundler 1.7.6 with the "undefined method `spec' for nil" bug
|
4
9
|
before_install: gem install bundler
|
5
|
-
|
10
|
+
|
6
11
|
rvm:
|
7
12
|
- 1.9.3
|
8
|
-
- 2.0
|
13
|
+
- 2.0
|
9
14
|
- 2.1
|
10
15
|
- 2.2
|
11
|
-
- 2.3
|
16
|
+
- 2.3
|
17
|
+
- 2.4
|
12
18
|
- ruby-head
|
13
19
|
- jruby-head
|
14
|
-
|
20
|
+
|
21
|
+
gemfile:
|
22
|
+
- gemfiles/redis_3_x.gemfile
|
23
|
+
- gemfiles/redis_4_x.gemfile
|
15
24
|
|
16
25
|
matrix:
|
17
26
|
allow_failures:
|
18
27
|
- rvm: jruby-head
|
19
28
|
- rvm: ruby-head
|
29
|
+
exclude:
|
30
|
+
- rvm: 1.9.3
|
31
|
+
gemfile: gemfiles/redis_4_x.gemfile
|
32
|
+
- rvm: 2.0
|
33
|
+
gemfile: gemfiles/redis_4_x.gemfile
|
34
|
+
- rvm: 2.1
|
35
|
+
gemfile: gemfiles/redis_4_x.gemfile
|
data/Appraisals
ADDED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,23 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 1.5.0
|
4
|
+
|
5
|
+
Breaking Changes
|
6
|
+
|
7
|
+
* None
|
8
|
+
|
9
|
+
Added
|
10
|
+
|
11
|
+
* [Support for Redis v4 and above](https://github.com/redis-store/redis-store/pull/292)
|
12
|
+
* [Support for distributed mget/read_multi in Redis v4](https://github.com/redis-store/redis-store/pull/282)
|
13
|
+
* [Tests for Namespace#flushdb](https://github.com/redis-store/redis-store/pull/299)
|
14
|
+
* [Support for UNIX Socket path connections](https://github.com/redis-store/redis-store/pull/298)
|
15
|
+
* [HashRing configuration for DistributedStore](https://github.com/redis-store/redis-store/pull/304)
|
16
|
+
|
17
|
+
Fixed
|
18
|
+
|
19
|
+
* [Inefficient use of KEYS when calling FLUSHDB without a namespace](https://github.com/redis-store/redis-store/pull/297)
|
20
|
+
|
3
21
|
## 1.4.1
|
4
22
|
|
5
23
|
Breaking Changes
|
data/Gemfile
CHANGED
data/Rakefile
CHANGED
@@ -2,3 +2,11 @@ require 'bundler/setup'
|
|
2
2
|
require 'rake'
|
3
3
|
require 'bundler/gem_tasks'
|
4
4
|
require 'redis-store/testing/tasks'
|
5
|
+
require 'appraisal'
|
6
|
+
|
7
|
+
|
8
|
+
if !ENV["APPRAISAL_INITIALIZED"] && !ENV["TRAVIS"]
|
9
|
+
task :default do
|
10
|
+
sh "appraisal install && rake appraisal default"
|
11
|
+
end
|
12
|
+
end
|
@@ -6,12 +6,12 @@ class Redis
|
|
6
6
|
attr_reader :ring
|
7
7
|
|
8
8
|
def initialize(addresses, options = { })
|
9
|
-
nodes = addresses.map do |address|
|
10
|
-
::Redis::Store.new _merge_options(address, options)
|
11
|
-
end
|
12
|
-
|
13
9
|
_extend_namespace options
|
14
|
-
@ring = Redis::HashRing.new
|
10
|
+
@ring = options[:ring] || Redis::HashRing.new([], options[:replicas] || Redis::HashRing::POINTS_PER_SERVER)
|
11
|
+
|
12
|
+
addresses.each do |address|
|
13
|
+
@ring.add_node(::Redis::Store.new _merge_options(address, options))
|
14
|
+
end
|
15
15
|
end
|
16
16
|
|
17
17
|
def nodes
|
data/lib/redis/store.rb
CHANGED
@@ -42,8 +42,17 @@ class Redis
|
|
42
42
|
end
|
43
43
|
|
44
44
|
def to_s
|
45
|
-
|
46
|
-
|
45
|
+
"Redis Client connected to #{location} against DB #{@client.db}"
|
46
|
+
end
|
47
|
+
|
48
|
+
def location
|
49
|
+
if @client.path
|
50
|
+
@client.path
|
51
|
+
else
|
52
|
+
h = @client.host
|
53
|
+
h = "[#{h}]" if h.include?(":")
|
54
|
+
"#{h}:#{@client.port}"
|
55
|
+
end
|
47
56
|
end
|
48
57
|
|
49
58
|
private
|
data/lib/redis/store/factory.rb
CHANGED
@@ -62,27 +62,33 @@ class Redis
|
|
62
62
|
end
|
63
63
|
|
64
64
|
def self.host_options?(options)
|
65
|
-
|
66
|
-
options
|
67
|
-
else
|
68
|
-
nil # just to be clear
|
69
|
-
end
|
65
|
+
options.keys.any? {|n| [:host, :db, :port, :path].include?(n) }
|
70
66
|
end
|
71
67
|
|
72
68
|
def self.extract_host_options_from_uri(uri)
|
73
69
|
uri = URI.parse(uri)
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
70
|
+
if uri.scheme == "unix"
|
71
|
+
options = { :path => uri.path }
|
72
|
+
else
|
73
|
+
_, db, namespace = if uri.path
|
74
|
+
uri.path.split(/\//)
|
75
|
+
end
|
76
|
+
|
77
|
+
options = {
|
78
|
+
:host => uri.hostname,
|
79
|
+
:port => uri.port || DEFAULT_PORT,
|
80
|
+
:password => uri.password.nil? ? nil : CGI::unescape(uri.password.to_s)
|
81
|
+
}
|
82
|
+
|
83
|
+
options[:db] = db.to_i if db
|
84
|
+
options[:namespace] = namespace if namespace
|
85
|
+
end
|
86
|
+
if uri.query
|
87
|
+
query = Hash[URI.decode_www_form(uri.query)]
|
88
|
+
query.each do |(key, value)|
|
89
|
+
options[key.to_sym] = value
|
90
|
+
end
|
91
|
+
end
|
86
92
|
|
87
93
|
options
|
88
94
|
end
|
@@ -47,14 +47,14 @@ class Redis
|
|
47
47
|
super(*keys.map {|key| interpolate(key) }) if keys.any?
|
48
48
|
end
|
49
49
|
|
50
|
-
def mget(*keys)
|
50
|
+
def mget(*keys, &blk)
|
51
51
|
options = (keys.pop if keys.last.is_a? Hash) || {}
|
52
52
|
if keys.any?
|
53
53
|
# Serialization gets extended before Namespace does, so we need to pass options further
|
54
54
|
if singleton_class.ancestors.include? Serialization
|
55
|
-
super(*keys.map {|key| interpolate(key) }, options)
|
55
|
+
super(*keys.map {|key| interpolate(key) }, options, &blk)
|
56
56
|
else
|
57
|
-
super(*keys.map {|key| interpolate(key) })
|
57
|
+
super(*keys.map {|key| interpolate(key) }, &blk)
|
58
58
|
end
|
59
59
|
end
|
60
60
|
end
|
@@ -72,6 +72,7 @@ class Redis
|
|
72
72
|
end
|
73
73
|
|
74
74
|
def flushdb
|
75
|
+
return super unless namespace_str
|
75
76
|
keys.each_slice(FLUSHDB_BATCH_SIZE) { |key_slice| del(*key_slice) }
|
76
77
|
end
|
77
78
|
|
@@ -17,10 +17,11 @@ class Redis
|
|
17
17
|
_unmarshal super(key), options
|
18
18
|
end
|
19
19
|
|
20
|
-
def mget(*keys)
|
20
|
+
def mget(*keys, &blk)
|
21
21
|
options = keys.pop if keys.last.is_a?(Hash)
|
22
|
-
super(*keys)
|
23
|
-
_unmarshal
|
22
|
+
super(*keys) do |reply|
|
23
|
+
reply.map! { |value| _unmarshal value, options }
|
24
|
+
blk ? blk.call(reply) : reply
|
24
25
|
end
|
25
26
|
end
|
26
27
|
|
data/lib/redis/store/version.rb
CHANGED
data/redis-store.gemspec
CHANGED
@@ -39,6 +39,50 @@ describe "Redis::DistributedStore" do
|
|
39
39
|
@dmr.get("rabbit").must_equal(@rabbit)
|
40
40
|
end
|
41
41
|
|
42
|
+
it "mget" do
|
43
|
+
@dmr.set "rabbit2", @white_rabbit
|
44
|
+
begin
|
45
|
+
@dmr.mget "rabbit", "rabbit2" do |rabbits|
|
46
|
+
rabbit, rabbit2 = rabbits
|
47
|
+
rabbits.length.must_equal(2)
|
48
|
+
rabbit.must_equal(@rabbit)
|
49
|
+
rabbit2.must_equal(@white_rabbit)
|
50
|
+
end
|
51
|
+
rescue Redis::Distributed::CannotDistribute
|
52
|
+
# Not supported on redis-rb < 4, and hence Ruby < 2.2.
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
it "mapped_mget" do
|
57
|
+
@dmr.set "rabbit2", @white_rabbit
|
58
|
+
begin
|
59
|
+
result = @dmr.mapped_mget("rabbit", "rabbit2")
|
60
|
+
result.keys.must_equal %w[ rabbit rabbit2 ]
|
61
|
+
result["rabbit"].must_equal @rabbit
|
62
|
+
result["rabbit2"].must_equal @white_rabbit
|
63
|
+
rescue Redis::Distributed::CannotDistribute
|
64
|
+
# Not supported on redis-rb < 4, and hence Ruby < 2.2.
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
it "passes through ring replica options" do
|
69
|
+
dmr = Redis::DistributedStore.new [
|
70
|
+
{:host => "localhost", :port => "6380", :db => 0},
|
71
|
+
{:host => "localhost", :port => "6381", :db => 0}
|
72
|
+
], replicas: 1024
|
73
|
+
dmr.ring.replicas.must_equal 1024
|
74
|
+
end
|
75
|
+
|
76
|
+
it "uses a custom ring object" do
|
77
|
+
my_ring = Redis::HashRing.new
|
78
|
+
dmr = Redis::DistributedStore.new [
|
79
|
+
{:host => "localhost", :port => "6380", :db => 0},
|
80
|
+
{:host => "localhost", :port => "6381", :db => 0}
|
81
|
+
], ring: my_ring
|
82
|
+
dmr.ring.must_equal my_ring
|
83
|
+
dmr.ring.nodes.length.must_equal 2
|
84
|
+
end
|
85
|
+
|
42
86
|
describe '#redis_version' do
|
43
87
|
it 'returns redis version' do
|
44
88
|
@dmr.nodes.first.expects(:redis_version)
|
@@ -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 path" do
|
26
|
+
store = Redis::Store::Factory.create :path => "/var/run/redis.sock"
|
27
|
+
store.to_s.must_equal("Redis Client connected to /var/run/redis.sock against DB 0")
|
28
|
+
end
|
29
|
+
|
25
30
|
it "uses specified db" do
|
26
31
|
store = Redis::Store::Factory.create :host => "localhost", :port => 6380, :db => 13
|
27
32
|
store.to_s.must_equal("Redis Client connected to localhost:6380 against DB 13")
|
@@ -115,6 +120,11 @@ describe "Redis::Store::Factory" do
|
|
115
120
|
store.to_s.must_equal("Redis Client connected to 127.0.0.1:6380 against DB 0")
|
116
121
|
end
|
117
122
|
|
123
|
+
it "uses specified path" do
|
124
|
+
store = Redis::Store::Factory.create "unix:///var/run/redis.sock"
|
125
|
+
store.to_s.must_equal("Redis Client connected to /var/run/redis.sock against DB 0")
|
126
|
+
end
|
127
|
+
|
118
128
|
it "uses specified db" do
|
119
129
|
store = Redis::Store::Factory.create "redis://127.0.0.1:6380/13"
|
120
130
|
store.to_s.must_equal("Redis Client connected to 127.0.0.1:6380 against DB 13")
|
@@ -125,6 +135,16 @@ describe "Redis::Store::Factory" do
|
|
125
135
|
store.to_s.must_equal("Redis Client connected to 127.0.0.1:6379 against DB 0 with namespace theplaylist")
|
126
136
|
end
|
127
137
|
|
138
|
+
it "uses specified via query namespace" do
|
139
|
+
store = Redis::Store::Factory.create "redis://127.0.0.1:6379/0?namespace=theplaylist"
|
140
|
+
store.to_s.must_equal("Redis Client connected to 127.0.0.1:6379 against DB 0 with namespace theplaylist")
|
141
|
+
end
|
142
|
+
|
143
|
+
it "uses specified namespace with path" do
|
144
|
+
store = Redis::Store::Factory.create "unix:///var/run/redis.sock?db=2&namespace=theplaylist"
|
145
|
+
store.to_s.must_equal("Redis Client connected to /var/run/redis.sock against DB 2 with namespace theplaylist")
|
146
|
+
end
|
147
|
+
|
128
148
|
it "uses specified password" do
|
129
149
|
store = Redis::Store::Factory.create "redis://:secret@127.0.0.1:6379/0/theplaylist"
|
130
150
|
store.instance_variable_get(:@client).password.must_equal("secret")
|
@@ -139,8 +139,18 @@ describe "Redis::Store::Namespace" do
|
|
139
139
|
end
|
140
140
|
|
141
141
|
it "should namespace mget" do
|
142
|
-
|
143
|
-
|
142
|
+
client.expects(:call).with([:mget, "#{@namespace}:rabbit", "#{@namespace}:white_rabbit"]).returns(%w[ foo bar ])
|
143
|
+
store.mget "rabbit", "white_rabbit" do |result|
|
144
|
+
result.must_equal(%w[ foo bar ])
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
it "should namespace mapped_mget" do
|
149
|
+
client.expects(:process).with([[:mget, "#{@namespace}:rabbit", "#{@namespace}:white_rabbit"]]).returns(%w[ foo bar ])
|
150
|
+
result = store.mapped_mget "rabbit", "white_rabbit"
|
151
|
+
result.keys.must_equal %w[ rabbit white_rabbit ]
|
152
|
+
result["rabbit"].must_equal "foo"
|
153
|
+
result["white_rabbit"].must_equal "bar"
|
144
154
|
end
|
145
155
|
|
146
156
|
it "should namespace expire" do
|
@@ -157,5 +167,20 @@ describe "Redis::Store::Namespace" do
|
|
157
167
|
client.expects(:call).with([:watch,"#{@namespace}:rabbit"]).once
|
158
168
|
store.watch("rabbit")
|
159
169
|
end
|
170
|
+
|
171
|
+
it "wraps flushdb with appropriate KEYS * calls" do
|
172
|
+
client.expects(:call).with([:flushdb]).never
|
173
|
+
client.expects(:call).with([:keys,"#{@namespace}:*"]).once.returns(["rabbit"])
|
174
|
+
client.expects(:call).with([:del,"#{@namespace}:rabbit"]).once
|
175
|
+
store.flushdb
|
176
|
+
end
|
177
|
+
|
178
|
+
it "skips flushdb wrapping if the namespace is nil" do
|
179
|
+
client.expects(:call).with([:flushdb])
|
180
|
+
client.expects(:call).with([:keys]).never
|
181
|
+
store.with_namespace(nil) do
|
182
|
+
store.flushdb
|
183
|
+
end
|
184
|
+
end
|
160
185
|
end
|
161
186
|
end
|
@@ -97,28 +97,39 @@ describe "Redis::Serialization" do
|
|
97
97
|
@store.get("rabbit", :raw => true).must_equal(%(#<OpenStruct color="white">))
|
98
98
|
end
|
99
99
|
|
100
|
-
it "
|
100
|
+
it "unmarshals on multi get" do
|
101
101
|
@store.set "rabbit2", @white_rabbit
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
102
|
+
@store.mget "rabbit", "rabbit2" do |rabbits|
|
103
|
+
rabbit, rabbit2 = rabbits
|
104
|
+
rabbits.length.must_equal(2)
|
105
|
+
rabbit.must_equal(@rabbit)
|
106
|
+
rabbit2.must_equal(@white_rabbit)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
it "unmarshals on mapped_mget" do
|
111
|
+
@store.set "rabbit2", @white_rabbit
|
112
|
+
result = @store.mapped_mget("rabbit", "rabbit2")
|
113
|
+
result.keys.must_equal %w[ rabbit rabbit2 ]
|
114
|
+
result["rabbit"].must_equal @rabbit
|
115
|
+
result["rabbit2"].must_equal @white_rabbit
|
107
116
|
end
|
108
117
|
|
109
118
|
if RUBY_VERSION.match /1\.9/
|
110
119
|
it "doesn't unmarshal on multi get if raw option is true" do
|
111
120
|
@store.set "rabbit2", @white_rabbit
|
112
|
-
|
113
|
-
|
114
|
-
|
121
|
+
@store.mget "rabbit", "rabbit2", :raw => true do |rabbit, rabbit2|
|
122
|
+
rabbit.must_equal("\x04\bU:\x0FOpenStruct{\x06:\tnameI\"\nbunny\x06:\x06EF")
|
123
|
+
rabbit2.must_equal("\x04\bU:\x0FOpenStruct{\x06:\ncolorI\"\nwhite\x06:\x06EF")
|
124
|
+
end
|
115
125
|
end
|
116
126
|
else
|
117
127
|
it "doesn't unmarshal on multi get if raw option is true" do
|
118
128
|
@store.set "rabbit2", @white_rabbit
|
119
|
-
|
120
|
-
|
121
|
-
|
129
|
+
@store.mget "rabbit", "rabbit2", :raw => true do |rabbit, rabbit2|
|
130
|
+
rabbit.must_include("\x04\bU:\x0FOpenStruct{\x06:\tname")
|
131
|
+
rabbit2.must_include("\x04\bU:\x0FOpenStruct{\x06:\ncolor")
|
132
|
+
end
|
122
133
|
end
|
123
134
|
end
|
124
135
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redis-store
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Luca Guidi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-04-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redis
|
@@ -142,6 +142,20 @@ dependencies:
|
|
142
142
|
- - ">="
|
143
143
|
- !ruby/object:Gem::Version
|
144
144
|
version: '0'
|
145
|
+
- !ruby/object:Gem::Dependency
|
146
|
+
name: appraisal
|
147
|
+
requirement: !ruby/object:Gem::Requirement
|
148
|
+
requirements:
|
149
|
+
- - "~>"
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
version: '2.0'
|
152
|
+
type: :development
|
153
|
+
prerelease: false
|
154
|
+
version_requirements: !ruby/object:Gem::Requirement
|
155
|
+
requirements:
|
156
|
+
- - "~>"
|
157
|
+
- !ruby/object:Gem::Version
|
158
|
+
version: '2.0'
|
145
159
|
description: Namespaced Rack::Session, Rack::Cache, I18n and cache Redis stores for
|
146
160
|
Ruby web frameworks.
|
147
161
|
email:
|
@@ -152,11 +166,14 @@ extra_rdoc_files: []
|
|
152
166
|
files:
|
153
167
|
- ".gitignore"
|
154
168
|
- ".travis.yml"
|
169
|
+
- Appraisals
|
155
170
|
- CHANGELOG.md
|
156
171
|
- Gemfile
|
157
172
|
- MIT-LICENSE
|
158
173
|
- README.md
|
159
174
|
- Rakefile
|
175
|
+
- gemfiles/redis_3_x.gemfile
|
176
|
+
- gemfiles/redis_4_x.gemfile
|
160
177
|
- lib/redis-store.rb
|
161
178
|
- lib/redis/distributed_store.rb
|
162
179
|
- lib/redis/store.rb
|
@@ -198,7 +215,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
198
215
|
version: '0'
|
199
216
|
requirements: []
|
200
217
|
rubyforge_project: redis-store
|
201
|
-
rubygems_version: 2.
|
218
|
+
rubygems_version: 2.7.3
|
202
219
|
signing_key:
|
203
220
|
specification_version: 4
|
204
221
|
summary: Redis stores for Ruby frameworks
|