redis 3.0.0.rc1 → 3.0.0.rc2
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/.travis.yml +50 -0
- data/.travis/Gemfile +11 -0
- data/CHANGELOG.md +47 -19
- data/README.md +160 -149
- data/Rakefile +15 -50
- data/examples/pubsub.rb +1 -1
- data/examples/unicorn/config.ru +1 -1
- data/examples/unicorn/unicorn.rb +1 -1
- data/lib/redis.rb +790 -390
- data/lib/redis/client.rb +137 -49
- data/lib/redis/connection/hiredis.rb +26 -15
- data/lib/redis/connection/ruby.rb +170 -53
- data/lib/redis/connection/synchrony.rb +23 -35
- data/lib/redis/distributed.rb +92 -32
- data/lib/redis/errors.rb +4 -2
- data/lib/redis/pipeline.rb +17 -6
- data/lib/redis/version.rb +1 -1
- data/redis.gemspec +4 -6
- data/test/blocking_commands_test.rb +42 -0
- data/test/command_map_test.rb +18 -17
- data/test/commands_on_hashes_test.rb +13 -12
- data/test/commands_on_lists_test.rb +35 -45
- data/test/commands_on_sets_test.rb +55 -54
- data/test/commands_on_sorted_sets_test.rb +106 -105
- data/test/commands_on_strings_test.rb +64 -55
- data/test/commands_on_value_types_test.rb +66 -54
- data/test/connection_handling_test.rb +136 -151
- data/test/distributed_blocking_commands_test.rb +33 -40
- data/test/distributed_commands_on_hashes_test.rb +6 -7
- data/test/distributed_commands_on_lists_test.rb +13 -14
- data/test/distributed_commands_on_sets_test.rb +57 -58
- data/test/distributed_commands_on_sorted_sets_test.rb +11 -12
- data/test/distributed_commands_on_strings_test.rb +31 -32
- data/test/distributed_commands_on_value_types_test.rb +61 -46
- data/test/distributed_commands_requiring_clustering_test.rb +108 -108
- data/test/distributed_connection_handling_test.rb +14 -15
- data/test/distributed_internals_test.rb +7 -19
- data/test/distributed_key_tags_test.rb +36 -36
- data/test/distributed_persistence_control_commands_test.rb +17 -14
- data/test/distributed_publish_subscribe_test.rb +61 -69
- data/test/distributed_remote_server_control_commands_test.rb +39 -28
- data/test/distributed_sorting_test.rb +12 -13
- data/test/distributed_test.rb +40 -41
- data/test/distributed_transactions_test.rb +20 -21
- data/test/encoding_test.rb +12 -9
- data/test/error_replies_test.rb +42 -36
- data/test/helper.rb +118 -85
- data/test/helper_test.rb +20 -6
- data/test/internals_test.rb +167 -103
- data/test/lint/blocking_commands.rb +124 -0
- data/test/lint/hashes.rb +115 -93
- data/test/lint/lists.rb +86 -80
- data/test/lint/sets.rb +68 -62
- data/test/lint/sorted_sets.rb +200 -195
- data/test/lint/strings.rb +112 -94
- data/test/lint/value_types.rb +76 -55
- data/test/persistence_control_commands_test.rb +17 -12
- data/test/pipelining_commands_test.rb +135 -126
- data/test/publish_subscribe_test.rb +105 -110
- data/test/remote_server_control_commands_test.rb +74 -58
- data/test/sorting_test.rb +31 -29
- data/test/support/connection/hiredis.rb +1 -0
- data/test/support/connection/ruby.rb +1 -0
- data/test/support/connection/synchrony.rb +17 -0
- data/test/{redis_mock.rb → support/redis_mock.rb} +24 -21
- data/test/support/wire/synchrony.rb +24 -0
- data/test/support/wire/thread.rb +5 -0
- data/test/synchrony_driver.rb +9 -9
- data/test/test.conf +1 -1
- data/test/thread_safety_test.rb +21 -19
- data/test/transactions_test.rb +189 -118
- data/test/unknown_commands_test.rb +9 -8
- data/test/url_param_test.rb +46 -41
- metadata +28 -43
- data/TODO.md +0 -4
- data/benchmarking/thread_safety.rb +0 -38
- data/test/lint/internals.rb +0 -36
@@ -1,148 +1,148 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
|
3
|
-
require
|
4
|
-
require "redis/distributed"
|
3
|
+
require "helper"
|
5
4
|
|
6
|
-
|
7
|
-
log = StringIO.new
|
8
|
-
init Redis::Distributed.new(NODES, :logger => ::Logger.new(log))
|
9
|
-
end
|
5
|
+
class TestDistributedCommandsRequiringClustering < Test::Unit::TestCase
|
10
6
|
|
11
|
-
|
12
|
-
r.set("{qux}foo", "s1")
|
13
|
-
r.rename "{qux}foo", "{qux}bar"
|
7
|
+
include Helper::Distributed
|
14
8
|
|
15
|
-
|
16
|
-
|
17
|
-
|
9
|
+
def test_rename
|
10
|
+
r.set("{qux}foo", "s1")
|
11
|
+
r.rename "{qux}foo", "{qux}bar"
|
18
12
|
|
19
|
-
|
20
|
-
|
21
|
-
|
13
|
+
assert_equal "s1", r.get("{qux}bar")
|
14
|
+
assert_equal nil, r.get("{qux}foo")
|
15
|
+
end
|
22
16
|
|
23
|
-
|
17
|
+
def test_renamenx
|
18
|
+
r.set("{qux}foo", "s1")
|
19
|
+
r.set("{qux}bar", "s2")
|
24
20
|
|
25
|
-
|
26
|
-
assert "s2" == r.get("{qux}bar")
|
27
|
-
end
|
21
|
+
assert_equal false, r.renamenx("{qux}foo", "{qux}bar")
|
28
22
|
|
29
|
-
|
30
|
-
|
31
|
-
|
23
|
+
assert_equal "s1", r.get("{qux}foo")
|
24
|
+
assert_equal "s2", r.get("{qux}bar")
|
25
|
+
end
|
32
26
|
|
33
|
-
|
34
|
-
|
35
|
-
|
27
|
+
def test_brpoplpush
|
28
|
+
r.rpush "{qux}foo", "s1"
|
29
|
+
r.rpush "{qux}foo", "s2"
|
36
30
|
|
37
|
-
|
38
|
-
|
39
|
-
|
31
|
+
assert_equal "s2", r.brpoplpush("{qux}foo", "{qux}bar", :timeout => 1)
|
32
|
+
assert_equal ["s2"], r.lrange("{qux}bar", 0, -1)
|
33
|
+
end
|
40
34
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
assert ["s1", "s2"] == r.lrange("{qux}bar", 0, -1)
|
45
|
-
end
|
35
|
+
def test_rpoplpush
|
36
|
+
r.rpush "{qux}foo", "s1"
|
37
|
+
r.rpush "{qux}foo", "s2"
|
46
38
|
|
47
|
-
|
48
|
-
|
49
|
-
|
39
|
+
assert_equal "s2", r.rpoplpush("{qux}foo", "{qux}bar")
|
40
|
+
assert_equal ["s2"], r.lrange("{qux}bar", 0, -1)
|
41
|
+
assert_equal "s1", r.rpoplpush("{qux}foo", "{qux}bar")
|
42
|
+
assert_equal ["s1", "s2"], r.lrange("{qux}bar", 0, -1)
|
43
|
+
end
|
50
44
|
|
51
|
-
|
52
|
-
|
53
|
-
|
45
|
+
def test_smove
|
46
|
+
r.sadd "{qux}foo", "s1"
|
47
|
+
r.sadd "{qux}bar", "s2"
|
54
48
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
r.sadd "{qux}bar", "s2"
|
49
|
+
assert r.smove("{qux}foo", "{qux}bar", "s1")
|
50
|
+
assert r.sismember("{qux}bar", "s1")
|
51
|
+
end
|
59
52
|
|
60
|
-
|
61
|
-
|
53
|
+
def test_sinter
|
54
|
+
r.sadd "{qux}foo", "s1"
|
55
|
+
r.sadd "{qux}foo", "s2"
|
56
|
+
r.sadd "{qux}bar", "s2"
|
62
57
|
|
63
|
-
|
64
|
-
|
65
|
-
r.sadd "{qux}foo", "s2"
|
66
|
-
r.sadd "{qux}bar", "s2"
|
58
|
+
assert_equal ["s2"], r.sinter("{qux}foo", "{qux}bar")
|
59
|
+
end
|
67
60
|
|
68
|
-
|
61
|
+
def test_sinterstore
|
62
|
+
r.sadd "{qux}foo", "s1"
|
63
|
+
r.sadd "{qux}foo", "s2"
|
64
|
+
r.sadd "{qux}bar", "s2"
|
69
65
|
|
70
|
-
|
71
|
-
end
|
66
|
+
r.sinterstore("{qux}baz", "{qux}foo", "{qux}bar")
|
72
67
|
|
73
|
-
|
74
|
-
|
75
|
-
r.sadd "{qux}foo", "s2"
|
76
|
-
r.sadd "{qux}bar", "s2"
|
77
|
-
r.sadd "{qux}bar", "s3"
|
68
|
+
assert_equal ["s2"], r.smembers("{qux}baz")
|
69
|
+
end
|
78
70
|
|
79
|
-
|
80
|
-
|
71
|
+
def test_sunion
|
72
|
+
r.sadd "{qux}foo", "s1"
|
73
|
+
r.sadd "{qux}foo", "s2"
|
74
|
+
r.sadd "{qux}bar", "s2"
|
75
|
+
r.sadd "{qux}bar", "s3"
|
81
76
|
|
82
|
-
|
83
|
-
|
84
|
-
r.sadd "{qux}foo", "s2"
|
85
|
-
r.sadd "{qux}bar", "s2"
|
86
|
-
r.sadd "{qux}bar", "s3"
|
77
|
+
assert_equal ["s1", "s2", "s3"], r.sunion("{qux}foo", "{qux}bar").sort
|
78
|
+
end
|
87
79
|
|
88
|
-
|
80
|
+
def test_sunionstore
|
81
|
+
r.sadd "{qux}foo", "s1"
|
82
|
+
r.sadd "{qux}foo", "s2"
|
83
|
+
r.sadd "{qux}bar", "s2"
|
84
|
+
r.sadd "{qux}bar", "s3"
|
89
85
|
|
90
|
-
|
91
|
-
end
|
86
|
+
r.sunionstore("{qux}baz", "{qux}foo", "{qux}bar")
|
92
87
|
|
93
|
-
|
94
|
-
|
95
|
-
r.sadd "{qux}foo", "s2"
|
96
|
-
r.sadd "{qux}bar", "s2"
|
97
|
-
r.sadd "{qux}bar", "s3"
|
88
|
+
assert_equal ["s1", "s2", "s3"], r.smembers("{qux}baz").sort
|
89
|
+
end
|
98
90
|
|
99
|
-
|
100
|
-
|
101
|
-
|
91
|
+
def test_sdiff
|
92
|
+
r.sadd "{qux}foo", "s1"
|
93
|
+
r.sadd "{qux}foo", "s2"
|
94
|
+
r.sadd "{qux}bar", "s2"
|
95
|
+
r.sadd "{qux}bar", "s3"
|
102
96
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
r.sadd "{qux}bar", "s2"
|
107
|
-
r.sadd "{qux}bar", "s3"
|
97
|
+
assert_equal ["s1"], r.sdiff("{qux}foo", "{qux}bar")
|
98
|
+
assert_equal ["s3"], r.sdiff("{qux}bar", "{qux}foo")
|
99
|
+
end
|
108
100
|
|
109
|
-
|
101
|
+
def test_sdiffstore
|
102
|
+
r.sadd "{qux}foo", "s1"
|
103
|
+
r.sadd "{qux}foo", "s2"
|
104
|
+
r.sadd "{qux}bar", "s2"
|
105
|
+
r.sadd "{qux}bar", "s3"
|
110
106
|
|
111
|
-
|
112
|
-
end
|
107
|
+
r.sdiffstore("{qux}baz", "{qux}foo", "{qux}bar")
|
113
108
|
|
114
|
-
|
115
|
-
|
116
|
-
r.set("{qux}foo:2", "s2")
|
109
|
+
assert_equal ["s1"], r.smembers("{qux}baz")
|
110
|
+
end
|
117
111
|
|
118
|
-
|
119
|
-
|
112
|
+
def test_sort
|
113
|
+
r.set("{qux}foo:1", "s1")
|
114
|
+
r.set("{qux}foo:2", "s2")
|
120
115
|
|
121
|
-
|
122
|
-
|
123
|
-
end
|
116
|
+
r.rpush("{qux}bar", "1")
|
117
|
+
r.rpush("{qux}bar", "2")
|
124
118
|
|
125
|
-
|
126
|
-
|
127
|
-
|
119
|
+
assert_equal ["s1"], r.sort("{qux}bar", :get => "{qux}foo:*", :limit => [0, 1])
|
120
|
+
assert_equal ["s2"], r.sort("{qux}bar", :get => "{qux}foo:*", :limit => [0, 1], :order => "desc alpha")
|
121
|
+
end
|
128
122
|
|
129
|
-
|
130
|
-
|
123
|
+
def test_sort_with_an_array_of_gets
|
124
|
+
r.set("{qux}foo:1:a", "s1a")
|
125
|
+
r.set("{qux}foo:1:b", "s1b")
|
131
126
|
|
132
|
-
|
133
|
-
|
127
|
+
r.set("{qux}foo:2:a", "s2a")
|
128
|
+
r.set("{qux}foo:2:b", "s2b")
|
134
129
|
|
135
|
-
|
136
|
-
|
137
|
-
|
130
|
+
r.rpush("{qux}bar", "1")
|
131
|
+
r.rpush("{qux}bar", "2")
|
132
|
+
|
133
|
+
assert_equal [["s1a", "s1b"]], r.sort("{qux}bar", :get => ["{qux}foo:*:a", "{qux}foo:*:b"], :limit => [0, 1])
|
134
|
+
assert_equal [["s2a", "s2b"]], r.sort("{qux}bar", :get => ["{qux}foo:*:a", "{qux}foo:*:b"], :limit => [0, 1], :order => "desc alpha")
|
135
|
+
assert_equal [["s1a", "s1b"], ["s2a", "s2b"]], r.sort("{qux}bar", :get => ["{qux}foo:*:a", "{qux}foo:*:b"])
|
136
|
+
end
|
138
137
|
|
139
|
-
|
140
|
-
|
141
|
-
|
138
|
+
def test_sort_with_store
|
139
|
+
r.set("{qux}foo:1", "s1")
|
140
|
+
r.set("{qux}foo:2", "s2")
|
142
141
|
|
143
|
-
|
144
|
-
|
142
|
+
r.rpush("{qux}bar", "1")
|
143
|
+
r.rpush("{qux}bar", "2")
|
145
144
|
|
146
|
-
|
147
|
-
|
145
|
+
r.sort("{qux}bar", :get => "{qux}foo:*", :store => "{qux}baz")
|
146
|
+
assert_equal ["s1", "s2"], r.lrange("{qux}baz", 0, -1)
|
147
|
+
end
|
148
148
|
end
|
@@ -1,24 +1,23 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
|
3
|
-
require
|
4
|
-
require "redis/distributed"
|
3
|
+
require "helper"
|
5
4
|
|
6
|
-
|
7
|
-
log = StringIO.new
|
8
|
-
init Redis::Distributed.new(NODES, :logger => ::Logger.new(log))
|
9
|
-
end
|
5
|
+
class TestDistributedConnectionHandling < Test::Unit::TestCase
|
10
6
|
|
11
|
-
|
12
|
-
|
13
|
-
|
7
|
+
include Helper::Distributed
|
8
|
+
|
9
|
+
def test_ping
|
10
|
+
assert_equal ["PONG"], r.ping
|
11
|
+
end
|
14
12
|
|
15
|
-
|
16
|
-
|
13
|
+
def test_select
|
14
|
+
r.set "foo", "bar"
|
17
15
|
|
18
|
-
|
19
|
-
|
16
|
+
r.select 14
|
17
|
+
assert_equal nil, r.get("foo")
|
20
18
|
|
21
|
-
|
19
|
+
r.select 15
|
22
20
|
|
23
|
-
|
21
|
+
assert_equal "bar", r.get("foo")
|
22
|
+
end
|
24
23
|
end
|
@@ -1,27 +1,15 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
|
3
|
-
require
|
4
|
-
require File.expand_path("./redis_mock", File.dirname(__FILE__))
|
3
|
+
require "helper"
|
5
4
|
|
6
|
-
|
5
|
+
class TestDistributedInternals < Test::Unit::TestCase
|
7
6
|
|
8
|
-
|
7
|
+
include Helper::Distributed
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
end
|
14
|
-
|
15
|
-
$TEST_PIPELINING = false
|
16
|
-
|
17
|
-
load File.expand_path("./lint/internals.rb", File.dirname(__FILE__))
|
18
|
-
|
19
|
-
test "provides a meaningful inspect" do |r, _|
|
20
|
-
nodes = ["redis://localhost:6379/15", *NODES]
|
21
|
-
@r = Redis::Distributed.new nodes
|
9
|
+
def test_provides_a_meaningful_inspect
|
10
|
+
nodes = ["redis://localhost:#{PORT}/15", *NODES]
|
11
|
+
redis = Redis::Distributed.new nodes
|
22
12
|
|
23
|
-
|
24
|
-
"#{node} (Redis v#{@r.info.first["redis_version"]})"
|
13
|
+
assert_equal "#<Redis client v#{Redis::VERSION} for #{redis.nodes.map(&:id).join(', ')}>", redis.inspect
|
25
14
|
end
|
26
|
-
assert "#<Redis client v#{Redis::VERSION} connected to #{node_info.join(', ')}>" == @r.inspect
|
27
15
|
end
|
@@ -1,52 +1,52 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
|
3
|
-
require
|
4
|
-
require "redis/distributed"
|
3
|
+
require "helper"
|
5
4
|
|
6
|
-
|
7
|
-
log = StringIO.new
|
8
|
-
init Redis::Distributed.new(NODES, :logger => ::Logger.new(log))
|
9
|
-
end
|
10
|
-
|
11
|
-
test "hashes consistently" do
|
12
|
-
r1 = Redis::Distributed.new ["redis://localhost:6379/15", *NODES]
|
13
|
-
r2 = Redis::Distributed.new ["redis://localhost:6379/15", *NODES]
|
14
|
-
r3 = Redis::Distributed.new ["redis://localhost:6379/15", *NODES]
|
5
|
+
class TestDistributedKeyTags < Test::Unit::TestCase
|
15
6
|
|
16
|
-
|
17
|
-
|
18
|
-
end
|
7
|
+
include Helper
|
8
|
+
include Helper::Distributed
|
19
9
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
10
|
+
def test_hashes_consistently
|
11
|
+
r1 = Redis::Distributed.new ["redis://localhost:#{PORT}/15", *NODES]
|
12
|
+
r2 = Redis::Distributed.new ["redis://localhost:#{PORT}/15", *NODES]
|
13
|
+
r3 = Redis::Distributed.new ["redis://localhost:#{PORT}/15", *NODES]
|
24
14
|
|
25
|
-
|
26
|
-
|
15
|
+
assert_equal r1.node_for("foo").id, r2.node_for("foo").id
|
16
|
+
assert_equal r1.node_for("foo").id, r3.node_for("foo").id
|
27
17
|
end
|
28
18
|
|
29
|
-
|
30
|
-
|
19
|
+
def test_allows_clustering_of_keys
|
20
|
+
r = Redis::Distributed.new(NODES)
|
21
|
+
r.add_node("redis://localhost:#{PORT}/14")
|
22
|
+
r.flushdb
|
31
23
|
|
32
|
-
|
33
|
-
|
34
|
-
|
24
|
+
100.times do |i|
|
25
|
+
r.set "{foo}users:#{i}", i
|
26
|
+
end
|
35
27
|
|
36
|
-
|
37
|
-
|
28
|
+
assert_equal [0, 100], r.nodes.map { |node| node.keys.size }
|
29
|
+
end
|
38
30
|
|
39
|
-
|
40
|
-
|
31
|
+
def test_distributes_keys_if_no_clustering_is_used
|
32
|
+
r.add_node("redis://localhost:#{PORT}/14")
|
33
|
+
r.flushdb
|
41
34
|
|
42
|
-
|
43
|
-
|
44
|
-
r.add_node("redis://localhost:6379/14")
|
45
|
-
r.flushdb
|
35
|
+
r.set "users:1", 1
|
36
|
+
r.set "users:4", 4
|
46
37
|
|
47
|
-
|
48
|
-
r.set "foo:users:#{i}", i
|
38
|
+
assert_equal [1, 1], r.nodes.map { |node| node.keys.size }
|
49
39
|
end
|
50
40
|
|
51
|
-
|
41
|
+
def test_allows_passing_a_custom_tag_extractor
|
42
|
+
r = Redis::Distributed.new(NODES, :tag => /^(.+?):/)
|
43
|
+
r.add_node("redis://localhost:#{PORT}/14")
|
44
|
+
r.flushdb
|
45
|
+
|
46
|
+
100.times do |i|
|
47
|
+
r.set "foo:users:#{i}", i
|
48
|
+
end
|
49
|
+
|
50
|
+
assert_equal [0, 100], r.nodes.map { |node| node.keys.size }
|
51
|
+
end
|
52
52
|
end
|
@@ -1,23 +1,26 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
|
3
|
-
require
|
4
|
-
require "redis/distributed"
|
3
|
+
require "helper"
|
5
4
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
end
|
5
|
+
class TestDistributedPersistenceControlCommands < Test::Unit::TestCase
|
6
|
+
|
7
|
+
include Helper::Distributed
|
10
8
|
|
11
|
-
|
12
|
-
|
13
|
-
|
9
|
+
def test_save
|
10
|
+
redis_mock(:save => lambda { "+SAVE" }) do |redis|
|
11
|
+
assert_equal ["SAVE"], redis.save
|
12
|
+
end
|
14
13
|
end
|
15
14
|
|
16
|
-
|
17
|
-
|
15
|
+
def test_bgsave
|
16
|
+
redis_mock(:bgsave => lambda { "+BGSAVE" }) do |redis|
|
17
|
+
assert_equal ["BGSAVE"], redis.bgsave
|
18
|
+
end
|
18
19
|
end
|
19
|
-
end
|
20
20
|
|
21
|
-
|
22
|
-
|
21
|
+
def test_lastsave
|
22
|
+
redis_mock(:lastsave => lambda { "+LASTSAVE" }) do |redis|
|
23
|
+
assert_equal ["LASTSAVE"], redis.lastsave
|
24
|
+
end
|
25
|
+
end
|
23
26
|
end
|