redis 3.0.0.rc2 → 3.0.0
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.
- data/.order +169 -0
- data/CHANGELOG.md +79 -9
- data/README.md +7 -0
- data/Rakefile +167 -0
- data/lib/redis.rb +1265 -1148
- data/lib/redis/client.rb +11 -18
- data/lib/redis/distributed.rb +337 -280
- data/lib/redis/pipeline.rb +12 -4
- data/lib/redis/version.rb +1 -1
- data/redis.gemspec +1 -1
- data/test/commands_on_lists_test.rb +0 -30
- data/test/commands_on_strings_test.rb +0 -6
- data/test/distributed_scripting_test.rb +102 -0
- data/test/internals_test.rb +33 -35
- data/test/lint/lists.rb +42 -12
- data/test/lint/strings.rb +6 -0
- data/test/lint/value_types.rb +10 -6
- data/test/scripting_test.rb +78 -0
- metadata +12 -8
data/lib/redis/pipeline.rb
CHANGED
@@ -9,13 +9,17 @@ class Redis
|
|
9
9
|
attr :futures
|
10
10
|
|
11
11
|
def initialize
|
12
|
-
@
|
12
|
+
@with_reconnect = true
|
13
13
|
@shutdown = false
|
14
14
|
@futures = []
|
15
15
|
end
|
16
16
|
|
17
|
+
def with_reconnect?
|
18
|
+
@with_reconnect
|
19
|
+
end
|
20
|
+
|
17
21
|
def without_reconnect?
|
18
|
-
|
22
|
+
!@with_reconnect
|
19
23
|
end
|
20
24
|
|
21
25
|
def shutdown?
|
@@ -41,11 +45,15 @@ class Redis
|
|
41
45
|
@futures.map { |f| f._command }
|
42
46
|
end
|
43
47
|
|
44
|
-
def
|
45
|
-
@
|
48
|
+
def with_reconnect(val=true)
|
49
|
+
@with_reconnect = false unless val
|
46
50
|
yield
|
47
51
|
end
|
48
52
|
|
53
|
+
def without_reconnect(&blk)
|
54
|
+
with_reconnect(false, &blk)
|
55
|
+
end
|
56
|
+
|
49
57
|
def finish(replies, &blk)
|
50
58
|
if blk
|
51
59
|
futures.each_with_index.map do |future, i|
|
data/lib/redis/version.rb
CHANGED
data/redis.gemspec
CHANGED
@@ -11,7 +11,7 @@ Gem::Specification.new do |s|
|
|
11
11
|
|
12
12
|
s.homepage = "https://github.com/redis/redis-rb"
|
13
13
|
|
14
|
-
s.summary = "A Ruby client library for
|
14
|
+
s.summary = "A Ruby client library for Redis"
|
15
15
|
|
16
16
|
s.description = <<-EOS
|
17
17
|
A Ruby client that tries to match Redis' API one-to-one, while still
|
@@ -8,36 +8,6 @@ class TestCommandsOnLists < Test::Unit::TestCase
|
|
8
8
|
include Helper::Client
|
9
9
|
include Lint::Lists
|
10
10
|
|
11
|
-
def test_rpushx
|
12
|
-
r.rpushx "foo", "s1"
|
13
|
-
r.rpush "foo", "s2"
|
14
|
-
r.rpushx "foo", "s3"
|
15
|
-
|
16
|
-
assert_equal 2, r.llen("foo")
|
17
|
-
assert_equal ["s2", "s3"], r.lrange("foo", 0, -1)
|
18
|
-
end
|
19
|
-
|
20
|
-
def test_lpushx
|
21
|
-
r.lpushx "foo", "s1"
|
22
|
-
r.lpush "foo", "s2"
|
23
|
-
r.lpushx "foo", "s3"
|
24
|
-
|
25
|
-
assert_equal 2, r.llen("foo")
|
26
|
-
assert_equal ["s3", "s2"], r.lrange("foo", 0, -1)
|
27
|
-
end
|
28
|
-
|
29
|
-
def test_linsert
|
30
|
-
r.rpush "foo", "s1"
|
31
|
-
r.rpush "foo", "s3"
|
32
|
-
r.linsert "foo", :before, "s3", "s2"
|
33
|
-
|
34
|
-
assert_equal ["s1", "s2", "s3"], r.lrange("foo", 0, -1)
|
35
|
-
|
36
|
-
assert_raise(Redis::CommandError) do
|
37
|
-
r.linsert "foo", :anywhere, "s3", "s2"
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
11
|
def test_rpoplpush
|
42
12
|
r.rpush "foo", "s1"
|
43
13
|
r.rpush "foo", "s2"
|
@@ -0,0 +1,102 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require "helper"
|
4
|
+
|
5
|
+
class TestDistributedScripting < Test::Unit::TestCase
|
6
|
+
|
7
|
+
include Helper::Distributed
|
8
|
+
|
9
|
+
def to_sha(script)
|
10
|
+
r.script(:load, script).first
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_script_exists
|
14
|
+
return if version < "2.5.9" # 2.6-rc1
|
15
|
+
|
16
|
+
a = to_sha("return 1")
|
17
|
+
b = a.succ
|
18
|
+
|
19
|
+
assert_equal [true], r.script(:exists, a)
|
20
|
+
assert_equal [false], r.script(:exists, b)
|
21
|
+
assert_equal [[true]], r.script(:exists, [a])
|
22
|
+
assert_equal [[false]], r.script(:exists, [b])
|
23
|
+
assert_equal [[true, false]], r.script(:exists, [a, b])
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_script_flush
|
27
|
+
return if version < "2.5.9" # 2.6-rc1
|
28
|
+
|
29
|
+
sha = to_sha("return 1")
|
30
|
+
assert r.script(:exists, sha).first
|
31
|
+
assert_equal ["OK"], r.script(:flush)
|
32
|
+
assert !r.script(:exists, sha).first
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_script_kill
|
36
|
+
return if version < "2.5.9" # 2.6-rc1
|
37
|
+
|
38
|
+
redis_mock(:script => lambda { |arg| "+#{arg.upcase}" }) do |redis|
|
39
|
+
assert_equal ["KILL"], redis.script(:kill)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_eval
|
44
|
+
return if version < "2.5.9" # 2.6-rc1
|
45
|
+
|
46
|
+
assert_raises(Redis::Distributed::CannotDistribute) do
|
47
|
+
r.eval("return #KEYS")
|
48
|
+
end
|
49
|
+
|
50
|
+
assert_raises(Redis::Distributed::CannotDistribute) do
|
51
|
+
r.eval("return KEYS", ["k1", "k2"])
|
52
|
+
end
|
53
|
+
|
54
|
+
assert_equal ["k1"], r.eval("return KEYS", ["k1"])
|
55
|
+
assert_equal ["a1", "a2"], r.eval("return ARGV", ["k1"], ["a1", "a2"])
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_eval_with_options_hash
|
59
|
+
return if version < "2.5.9" # 2.6-rc1
|
60
|
+
|
61
|
+
assert_raises(Redis::Distributed::CannotDistribute) do
|
62
|
+
r.eval("return #KEYS", {})
|
63
|
+
end
|
64
|
+
|
65
|
+
assert_raises(Redis::Distributed::CannotDistribute) do
|
66
|
+
r.eval("return KEYS", { :keys => ["k1", "k2"] })
|
67
|
+
end
|
68
|
+
|
69
|
+
assert_equal ["k1"], r.eval("return KEYS", { :keys => ["k1"] })
|
70
|
+
assert_equal ["a1", "a2"], r.eval("return ARGV", { :keys => ["k1"], :argv => ["a1", "a2"] })
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_evalsha
|
74
|
+
return if version < "2.5.9" # 2.6-rc1
|
75
|
+
|
76
|
+
assert_raises(Redis::Distributed::CannotDistribute) do
|
77
|
+
r.evalsha(to_sha("return #KEYS"))
|
78
|
+
end
|
79
|
+
|
80
|
+
assert_raises(Redis::Distributed::CannotDistribute) do
|
81
|
+
r.evalsha(to_sha("return KEYS"), ["k1", "k2"])
|
82
|
+
end
|
83
|
+
|
84
|
+
assert_equal ["k1"], r.evalsha(to_sha("return KEYS"), ["k1"])
|
85
|
+
assert_equal ["a1", "a2"], r.evalsha(to_sha("return ARGV"), ["k1"], ["a1", "a2"])
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_evalsha_with_options_hash
|
89
|
+
return if version < "2.5.9" # 2.6-rc1
|
90
|
+
|
91
|
+
assert_raises(Redis::Distributed::CannotDistribute) do
|
92
|
+
r.evalsha(to_sha("return #KEYS"), {})
|
93
|
+
end
|
94
|
+
|
95
|
+
assert_raises(Redis::Distributed::CannotDistribute) do
|
96
|
+
r.evalsha(to_sha("return KEYS"), { :keys => ["k1", "k2"] })
|
97
|
+
end
|
98
|
+
|
99
|
+
assert_equal ["k1"], r.evalsha(to_sha("return KEYS"), { :keys => ["k1"] })
|
100
|
+
assert_equal ["a1", "a2"], r.evalsha(to_sha("return ARGV"), { :keys => ["k1"], :argv => ["a1", "a2"] })
|
101
|
+
end
|
102
|
+
end
|
data/test/internals_test.rb
CHANGED
@@ -117,54 +117,59 @@ class TestInternals < Test::Unit::TestCase
|
|
117
117
|
end
|
118
118
|
end
|
119
119
|
|
120
|
-
def
|
120
|
+
def close_on_ping(seq)
|
121
121
|
$request = 0
|
122
122
|
|
123
123
|
command = lambda do
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
124
|
+
idx = $request
|
125
|
+
$request += 1
|
126
|
+
|
127
|
+
rv = "+%d" % idx
|
128
|
+
rv = nil if seq.include?(idx)
|
129
|
+
rv
|
128
130
|
end
|
129
131
|
|
130
132
|
redis_mock(:ping => command, :timeout => 0.1) do |redis|
|
131
|
-
|
133
|
+
yield(redis)
|
132
134
|
end
|
133
135
|
end
|
134
136
|
|
135
|
-
def
|
136
|
-
|
137
|
+
def test_retry_by_default
|
138
|
+
close_on_ping([0]) do |redis|
|
139
|
+
assert_equal "1", redis.ping
|
140
|
+
end
|
141
|
+
end
|
137
142
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
143
|
+
def test_retry_when_wrapped_in_with_reconnect_true
|
144
|
+
close_on_ping([0]) do |redis|
|
145
|
+
redis.with_reconnect(true) do
|
146
|
+
assert_equal "1", redis.ping
|
142
147
|
end
|
143
148
|
end
|
149
|
+
end
|
144
150
|
|
145
|
-
|
151
|
+
def test_dont_retry_when_wrapped_in_with_reconnect_false
|
152
|
+
close_on_ping([0]) do |redis|
|
146
153
|
assert_raise Redis::ConnectionError do
|
147
|
-
redis.
|
154
|
+
redis.with_reconnect(false) do
|
148
155
|
redis.ping
|
149
156
|
end
|
150
157
|
end
|
151
|
-
|
152
|
-
assert !redis.client.connected?
|
153
158
|
end
|
154
159
|
end
|
155
160
|
|
156
|
-
def
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
when 2; nil # Close on second command
|
163
|
-
else "+%d" % $request
|
161
|
+
def test_dont_retry_when_wrapped_in_without_reconnect
|
162
|
+
close_on_ping([0]) do |redis|
|
163
|
+
assert_raise Redis::ConnectionError do
|
164
|
+
redis.without_reconnect do
|
165
|
+
redis.ping
|
166
|
+
end
|
164
167
|
end
|
165
168
|
end
|
169
|
+
end
|
166
170
|
|
167
|
-
|
171
|
+
def test_retry_only_once_when_read_raises_econnreset
|
172
|
+
close_on_ping([0, 1]) do |redis|
|
168
173
|
assert_raise Redis::ConnectionError do
|
169
174
|
redis.ping
|
170
175
|
end
|
@@ -174,22 +179,15 @@ class TestInternals < Test::Unit::TestCase
|
|
174
179
|
end
|
175
180
|
|
176
181
|
def test_don_t_retry_when_second_read_in_pipeline_raises_econnreset
|
177
|
-
|
178
|
-
|
179
|
-
command = lambda do
|
180
|
-
case ($request += 1)
|
181
|
-
when 2; nil # Close on second command
|
182
|
-
else "+%d" % $request
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
redis_mock(:ping => command, :timeout => 0.1) do |redis|
|
182
|
+
close_on_ping([1]) do |redis|
|
187
183
|
assert_raise Redis::ConnectionError do
|
188
184
|
redis.pipelined do
|
189
185
|
redis.ping
|
190
186
|
redis.ping # Second #read times out
|
191
187
|
end
|
192
188
|
end
|
189
|
+
|
190
|
+
assert !redis.client.connected?
|
193
191
|
end
|
194
192
|
end
|
195
193
|
|
data/test/lint/lists.rb
CHANGED
@@ -2,6 +2,31 @@ module Lint
|
|
2
2
|
|
3
3
|
module Lists
|
4
4
|
|
5
|
+
def test_lpush
|
6
|
+
r.lpush "foo", "s1"
|
7
|
+
r.lpush "foo", "s2"
|
8
|
+
|
9
|
+
assert_equal 2, r.llen("foo")
|
10
|
+
assert_equal "s2", r.lpop("foo")
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_variadic_lpush
|
14
|
+
return if version < "2.3.9" # 2.4-rc6
|
15
|
+
|
16
|
+
assert_equal 3, r.lpush("foo", ["s1", "s2", "s3"])
|
17
|
+
assert_equal 3, r.llen("foo")
|
18
|
+
assert_equal "s3", r.lpop("foo")
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_lpushx
|
22
|
+
r.lpushx "foo", "s1"
|
23
|
+
r.lpush "foo", "s2"
|
24
|
+
r.lpushx "foo", "s3"
|
25
|
+
|
26
|
+
assert_equal 2, r.llen("foo")
|
27
|
+
assert_equal ["s3", "s2"], r.lrange("foo", 0, -1)
|
28
|
+
end
|
29
|
+
|
5
30
|
def test_rpush
|
6
31
|
r.rpush "foo", "s1"
|
7
32
|
r.rpush "foo", "s2"
|
@@ -18,20 +43,13 @@ module Lint
|
|
18
43
|
assert_equal "s3", r.rpop("foo")
|
19
44
|
end
|
20
45
|
|
21
|
-
def
|
22
|
-
r.
|
23
|
-
r.
|
46
|
+
def test_rpushx
|
47
|
+
r.rpushx "foo", "s1"
|
48
|
+
r.rpush "foo", "s2"
|
49
|
+
r.rpushx "foo", "s3"
|
24
50
|
|
25
51
|
assert_equal 2, r.llen("foo")
|
26
|
-
assert_equal "s2", r.
|
27
|
-
end
|
28
|
-
|
29
|
-
def test_variadic_lpush
|
30
|
-
return if version < "2.3.9" # 2.4-rc6
|
31
|
-
|
32
|
-
assert_equal 3, r.lpush("foo", ["s1", "s2", "s3"])
|
33
|
-
assert_equal 3, r.llen("foo")
|
34
|
-
assert_equal "s3", r.lpop("foo")
|
52
|
+
assert_equal ["s2", "s3"], r.lrange("foo", 0, -1)
|
35
53
|
end
|
36
54
|
|
37
55
|
def test_llen
|
@@ -109,5 +127,17 @@ module Lint
|
|
109
127
|
assert_equal "s2", r.rpop("foo")
|
110
128
|
assert_equal 1, r.llen("foo")
|
111
129
|
end
|
130
|
+
|
131
|
+
def test_linsert
|
132
|
+
r.rpush "foo", "s1"
|
133
|
+
r.rpush "foo", "s3"
|
134
|
+
r.linsert "foo", :before, "s3", "s2"
|
135
|
+
|
136
|
+
assert_equal ["s1", "s2", "s3"], r.lrange("foo", 0, -1)
|
137
|
+
|
138
|
+
assert_raise(Redis::CommandError) do
|
139
|
+
r.linsert "foo", :anywhere, "s3", "s2"
|
140
|
+
end
|
141
|
+
end
|
112
142
|
end
|
113
143
|
end
|
data/test/lint/strings.rb
CHANGED
data/test/lint/value_types.rb
CHANGED
@@ -2,6 +2,10 @@ module Lint
|
|
2
2
|
|
3
3
|
module ValueTypes
|
4
4
|
|
5
|
+
def assert_in_range(range, value)
|
6
|
+
assert range.include?(value), "expected #{value} to be in #{range.inspect}"
|
7
|
+
end
|
8
|
+
|
5
9
|
def test_exists
|
6
10
|
assert_equal false, r.exists("foo")
|
7
11
|
|
@@ -29,7 +33,7 @@ module Lint
|
|
29
33
|
def test_expire
|
30
34
|
r.set("foo", "s1")
|
31
35
|
assert r.expire("foo", 1)
|
32
|
-
|
36
|
+
assert_in_range 0..1, r.ttl("foo")
|
33
37
|
end
|
34
38
|
|
35
39
|
def test_pexpire
|
@@ -37,13 +41,13 @@ module Lint
|
|
37
41
|
|
38
42
|
r.set("foo", "s1")
|
39
43
|
assert r.pexpire("foo", 1000)
|
40
|
-
|
44
|
+
assert_in_range 0..1, r.ttl("foo")
|
41
45
|
end
|
42
46
|
|
43
47
|
def test_expireat
|
44
48
|
r.set("foo", "s1")
|
45
49
|
assert r.expireat("foo", (Time.now + 1).to_i)
|
46
|
-
|
50
|
+
assert_in_range 0..1, r.ttl("foo")
|
47
51
|
end
|
48
52
|
|
49
53
|
def test_pexpireat
|
@@ -51,7 +55,7 @@ module Lint
|
|
51
55
|
|
52
56
|
r.set("foo", "s1")
|
53
57
|
assert r.pexpireat("foo", (Time.now + 1).to_i * 1_000)
|
54
|
-
|
58
|
+
assert_in_range 0..1, r.ttl("foo")
|
55
59
|
end
|
56
60
|
|
57
61
|
def test_persist
|
@@ -65,7 +69,7 @@ module Lint
|
|
65
69
|
def test_ttl
|
66
70
|
r.set("foo", "s1")
|
67
71
|
r.expire("foo", 1)
|
68
|
-
|
72
|
+
assert_in_range 0..1, r.ttl("foo")
|
69
73
|
end
|
70
74
|
|
71
75
|
def test_pttl
|
@@ -73,7 +77,7 @@ module Lint
|
|
73
77
|
|
74
78
|
r.set("foo", "s1")
|
75
79
|
r.expire("foo", 1)
|
76
|
-
|
80
|
+
assert_in_range 1..1000, r.pttl("foo")
|
77
81
|
end
|
78
82
|
|
79
83
|
def test_move
|