redis 2.0.0 → 2.2.1
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/.gitignore +8 -0
- data/CHANGELOG.md +49 -0
- data/README.md +208 -0
- data/Rakefile +183 -73
- data/TODO.md +4 -0
- data/benchmarking/logging.rb +62 -0
- data/benchmarking/pipeline.rb +51 -0
- data/benchmarking/speed.rb +21 -0
- data/benchmarking/suite.rb +24 -0
- data/benchmarking/thread_safety.rb +38 -0
- data/benchmarking/worker.rb +71 -0
- data/examples/basic.rb +15 -0
- data/examples/dist_redis.rb +43 -0
- data/examples/incr-decr.rb +17 -0
- data/examples/list.rb +26 -0
- data/examples/pubsub.rb +31 -0
- data/examples/sets.rb +36 -0
- data/examples/unicorn/config.ru +3 -0
- data/examples/unicorn/unicorn.rb +20 -0
- data/lib/redis/client.rb +149 -165
- data/lib/redis/connection/command_helper.rb +45 -0
- data/lib/redis/connection/hiredis.rb +49 -0
- data/lib/redis/connection/registry.rb +12 -0
- data/lib/redis/connection/ruby.rb +135 -0
- data/lib/redis/connection/synchrony.rb +129 -0
- data/lib/redis/connection.rb +9 -0
- data/lib/redis/distributed.rb +182 -7
- data/lib/redis/pipeline.rb +22 -1
- data/lib/redis/subscribe.rb +19 -4
- data/lib/redis/version.rb +3 -0
- data/lib/redis.rb +715 -155
- data/redis.gemspec +24 -0
- data/test/commands_on_hashes_test.rb +32 -0
- data/test/commands_on_lists_test.rb +60 -0
- data/test/commands_on_sets_test.rb +78 -0
- data/test/commands_on_sorted_sets_test.rb +109 -0
- data/test/commands_on_strings_test.rb +80 -0
- data/test/commands_on_value_types_test.rb +88 -0
- data/test/connection_handling_test.rb +88 -0
- data/test/db/.gitignore +1 -0
- data/test/distributed_blocking_commands_test.rb +53 -0
- data/test/distributed_commands_on_hashes_test.rb +12 -0
- data/test/distributed_commands_on_lists_test.rb +24 -0
- data/test/distributed_commands_on_sets_test.rb +85 -0
- data/test/distributed_commands_on_strings_test.rb +50 -0
- data/test/distributed_commands_on_value_types_test.rb +73 -0
- data/test/distributed_commands_requiring_clustering_test.rb +148 -0
- data/test/distributed_connection_handling_test.rb +25 -0
- data/test/distributed_internals_test.rb +27 -0
- data/test/distributed_key_tags_test.rb +53 -0
- data/test/distributed_persistence_control_commands_test.rb +24 -0
- data/test/distributed_publish_subscribe_test.rb +101 -0
- data/test/distributed_remote_server_control_commands_test.rb +43 -0
- data/test/distributed_sorting_test.rb +21 -0
- data/test/distributed_test.rb +59 -0
- data/test/distributed_transactions_test.rb +34 -0
- data/test/encoding_test.rb +16 -0
- data/test/error_replies_test.rb +53 -0
- data/test/helper.rb +145 -0
- data/test/internals_test.rb +160 -0
- data/test/lint/hashes.rb +114 -0
- data/test/lint/internals.rb +37 -0
- data/test/lint/lists.rb +93 -0
- data/test/lint/sets.rb +66 -0
- data/test/lint/sorted_sets.rb +167 -0
- data/test/lint/strings.rb +137 -0
- data/test/lint/value_types.rb +84 -0
- data/test/persistence_control_commands_test.rb +22 -0
- data/test/pipelining_commands_test.rb +123 -0
- data/test/publish_subscribe_test.rb +158 -0
- data/test/redis_mock.rb +80 -0
- data/test/remote_server_control_commands_test.rb +82 -0
- data/test/sorting_test.rb +44 -0
- data/test/synchrony_driver.rb +57 -0
- data/test/test.conf +8 -0
- data/test/thread_safety_test.rb +30 -0
- data/test/transactions_test.rb +100 -0
- data/test/unknown_commands_test.rb +14 -0
- data/test/url_param_test.rb +60 -0
- metadata +130 -22
- data/README.markdown +0 -120
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
require File.expand_path("./helper", File.dirname(__FILE__))
|
|
4
|
+
require "redis/distributed"
|
|
5
|
+
|
|
6
|
+
setup do
|
|
7
|
+
log = StringIO.new
|
|
8
|
+
init Redis::Distributed.new(NODES, :logger => ::Logger.new(log))
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
load './test/lint/sets.rb'
|
|
12
|
+
|
|
13
|
+
test "SMOVE" do |r|
|
|
14
|
+
assert_raise Redis::Distributed::CannotDistribute do
|
|
15
|
+
r.sadd "foo", "s1"
|
|
16
|
+
r.sadd "bar", "s2"
|
|
17
|
+
|
|
18
|
+
r.smove("foo", "bar", "s1")
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
test "SINTER" do |r|
|
|
23
|
+
assert_raise Redis::Distributed::CannotDistribute do
|
|
24
|
+
r.sadd "foo", "s1"
|
|
25
|
+
r.sadd "foo", "s2"
|
|
26
|
+
r.sadd "bar", "s2"
|
|
27
|
+
|
|
28
|
+
r.sinter("foo", "bar")
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
test "SINTERSTORE" do |r|
|
|
33
|
+
assert_raise Redis::Distributed::CannotDistribute do
|
|
34
|
+
r.sadd "foo", "s1"
|
|
35
|
+
r.sadd "foo", "s2"
|
|
36
|
+
r.sadd "bar", "s2"
|
|
37
|
+
|
|
38
|
+
r.sinterstore("baz", "foo", "bar")
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
test "SUNION" do |r|
|
|
43
|
+
assert_raise Redis::Distributed::CannotDistribute do
|
|
44
|
+
r.sadd "foo", "s1"
|
|
45
|
+
r.sadd "foo", "s2"
|
|
46
|
+
r.sadd "bar", "s2"
|
|
47
|
+
r.sadd "bar", "s3"
|
|
48
|
+
|
|
49
|
+
r.sunion("foo", "bar")
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
test "SUNIONSTORE" do |r|
|
|
54
|
+
assert_raise Redis::Distributed::CannotDistribute do
|
|
55
|
+
r.sadd "foo", "s1"
|
|
56
|
+
r.sadd "foo", "s2"
|
|
57
|
+
r.sadd "bar", "s2"
|
|
58
|
+
r.sadd "bar", "s3"
|
|
59
|
+
|
|
60
|
+
r.sunionstore("baz", "foo", "bar")
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
test "SDIFF" do |r|
|
|
65
|
+
assert_raise Redis::Distributed::CannotDistribute do
|
|
66
|
+
r.sadd "foo", "s1"
|
|
67
|
+
r.sadd "foo", "s2"
|
|
68
|
+
r.sadd "bar", "s2"
|
|
69
|
+
r.sadd "bar", "s3"
|
|
70
|
+
|
|
71
|
+
r.sdiff("foo", "bar")
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
test "SDIFFSTORE" do |r|
|
|
76
|
+
assert_raise Redis::Distributed::CannotDistribute do
|
|
77
|
+
r.sadd "foo", "s1"
|
|
78
|
+
r.sadd "foo", "s2"
|
|
79
|
+
r.sadd "bar", "s2"
|
|
80
|
+
r.sadd "bar", "s3"
|
|
81
|
+
|
|
82
|
+
r.sdiffstore("baz", "foo", "bar")
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
require File.expand_path("./helper", File.dirname(__FILE__))
|
|
4
|
+
require "redis/distributed"
|
|
5
|
+
|
|
6
|
+
setup do
|
|
7
|
+
log = StringIO.new
|
|
8
|
+
init Redis::Distributed.new(NODES, :logger => ::Logger.new(log))
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
load './test/lint/strings.rb'
|
|
12
|
+
|
|
13
|
+
test "MGET" do |r|
|
|
14
|
+
assert_raise Redis::Distributed::CannotDistribute do
|
|
15
|
+
r.mget("foo", "bar")
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
test "MGET mapped" do |r|
|
|
20
|
+
assert_raise Redis::Distributed::CannotDistribute do
|
|
21
|
+
r.mapped_mget("foo", "bar")
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
test "MSET" do |r|
|
|
26
|
+
assert_raise Redis::Distributed::CannotDistribute do
|
|
27
|
+
r.mset(:foo, "s1", :bar, "s2")
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
test "MSET mapped" do |r|
|
|
32
|
+
assert_raise Redis::Distributed::CannotDistribute do
|
|
33
|
+
r.mapped_mset(:foo => "s1", :bar => "s2")
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
test "MSETNX" do |r|
|
|
38
|
+
assert_raise Redis::Distributed::CannotDistribute do
|
|
39
|
+
r.set("foo", "s1")
|
|
40
|
+
r.msetnx(:foo, "s2", :bar, "s3")
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
test "MSETNX mapped" do |r|
|
|
45
|
+
assert_raise Redis::Distributed::CannotDistribute do
|
|
46
|
+
r.set("foo", "s1")
|
|
47
|
+
r.mapped_msetnx(:foo => "s2", :bar => "s3")
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
require File.expand_path("./helper", File.dirname(__FILE__))
|
|
4
|
+
require "redis/distributed"
|
|
5
|
+
|
|
6
|
+
setup do
|
|
7
|
+
log = StringIO.new
|
|
8
|
+
init(Redis::Distributed.new(NODES, :logger => ::Logger.new(log)))
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
load "./test/lint/value_types.rb"
|
|
12
|
+
|
|
13
|
+
test "DEL" do |r|
|
|
14
|
+
r.set "foo", "s1"
|
|
15
|
+
r.set "bar", "s2"
|
|
16
|
+
r.set "baz", "s3"
|
|
17
|
+
|
|
18
|
+
assert ["bar", "baz", "foo"] == r.keys("*").sort
|
|
19
|
+
|
|
20
|
+
assert 1 == r.del("foo")
|
|
21
|
+
|
|
22
|
+
assert ["bar", "baz"] == r.keys("*").sort
|
|
23
|
+
|
|
24
|
+
assert 2 == r.del("bar", "baz")
|
|
25
|
+
|
|
26
|
+
assert [] == r.keys("*").sort
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
test "RANDOMKEY" do |r|
|
|
30
|
+
assert_raise Redis::Distributed::CannotDistribute do
|
|
31
|
+
r.randomkey
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
test "RENAME" do |r|
|
|
36
|
+
assert_raise Redis::Distributed::CannotDistribute do
|
|
37
|
+
r.set("foo", "s1")
|
|
38
|
+
r.rename "foo", "bar"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
assert "s1" == r.get("foo")
|
|
42
|
+
assert nil == r.get("bar")
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
test "RENAMENX" do |r|
|
|
46
|
+
assert_raise Redis::Distributed::CannotDistribute do
|
|
47
|
+
r.set("foo", "s1")
|
|
48
|
+
r.rename "foo", "bar"
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
assert "s1" == r.get("foo")
|
|
52
|
+
assert nil == r.get("bar")
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
test "DBSIZE" do |r|
|
|
56
|
+
assert [0] == r.dbsize
|
|
57
|
+
|
|
58
|
+
r.set("foo", "s1")
|
|
59
|
+
|
|
60
|
+
assert [1] == r.dbsize
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
test "FLUSHDB" do |r|
|
|
64
|
+
r.set("foo", "s1")
|
|
65
|
+
r.set("bar", "s2")
|
|
66
|
+
|
|
67
|
+
assert [2] == r.dbsize
|
|
68
|
+
|
|
69
|
+
r.flushdb
|
|
70
|
+
|
|
71
|
+
assert [0] == r.dbsize
|
|
72
|
+
end
|
|
73
|
+
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
require File.expand_path("./helper", File.dirname(__FILE__))
|
|
4
|
+
require "redis/distributed"
|
|
5
|
+
|
|
6
|
+
setup do
|
|
7
|
+
log = StringIO.new
|
|
8
|
+
init Redis::Distributed.new(NODES, :logger => ::Logger.new(log))
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
test "RENAME" do |r|
|
|
12
|
+
r.set("{qux}foo", "s1")
|
|
13
|
+
r.rename "{qux}foo", "{qux}bar"
|
|
14
|
+
|
|
15
|
+
assert "s1" == r.get("{qux}bar")
|
|
16
|
+
assert nil == r.get("{qux}foo")
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
test "RENAMENX" do |r|
|
|
20
|
+
r.set("{qux}foo", "s1")
|
|
21
|
+
r.set("{qux}bar", "s2")
|
|
22
|
+
|
|
23
|
+
assert false == r.renamenx("{qux}foo", "{qux}bar")
|
|
24
|
+
|
|
25
|
+
assert "s1" == r.get("{qux}foo")
|
|
26
|
+
assert "s2" == r.get("{qux}bar")
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
test "BRPOPLPUSH" do |r|
|
|
30
|
+
r.rpush "{qux}foo", "s1"
|
|
31
|
+
r.rpush "{qux}foo", "s2"
|
|
32
|
+
|
|
33
|
+
assert_equal "s2", r.brpoplpush("{qux}foo", "{qux}bar", 1)
|
|
34
|
+
assert_equal ["s2"], r.lrange("{qux}bar", 0, -1)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
test "RPOPLPUSH" do |r|
|
|
38
|
+
r.rpush "{qux}foo", "s1"
|
|
39
|
+
r.rpush "{qux}foo", "s2"
|
|
40
|
+
|
|
41
|
+
assert "s2" == r.rpoplpush("{qux}foo", "{qux}bar")
|
|
42
|
+
assert ["s2"] == r.lrange("{qux}bar", 0, -1)
|
|
43
|
+
assert "s1" == r.rpoplpush("{qux}foo", "{qux}bar")
|
|
44
|
+
assert ["s1", "s2"] == r.lrange("{qux}bar", 0, -1)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
test "SMOVE" do |r|
|
|
48
|
+
r.sadd "{qux}foo", "s1"
|
|
49
|
+
r.sadd "{qux}bar", "s2"
|
|
50
|
+
|
|
51
|
+
assert r.smove("{qux}foo", "{qux}bar", "s1")
|
|
52
|
+
assert r.sismember("{qux}bar", "s1")
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
test "SINTER" do |r|
|
|
56
|
+
r.sadd "{qux}foo", "s1"
|
|
57
|
+
r.sadd "{qux}foo", "s2"
|
|
58
|
+
r.sadd "{qux}bar", "s2"
|
|
59
|
+
|
|
60
|
+
assert ["s2"] == r.sinter("{qux}foo", "{qux}bar")
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
test "SINTERSTORE" do |r|
|
|
64
|
+
r.sadd "{qux}foo", "s1"
|
|
65
|
+
r.sadd "{qux}foo", "s2"
|
|
66
|
+
r.sadd "{qux}bar", "s2"
|
|
67
|
+
|
|
68
|
+
r.sinterstore("{qux}baz", "{qux}foo", "{qux}bar")
|
|
69
|
+
|
|
70
|
+
assert ["s2"] == r.smembers("{qux}baz")
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
test "SUNION" do |r|
|
|
74
|
+
r.sadd "{qux}foo", "s1"
|
|
75
|
+
r.sadd "{qux}foo", "s2"
|
|
76
|
+
r.sadd "{qux}bar", "s2"
|
|
77
|
+
r.sadd "{qux}bar", "s3"
|
|
78
|
+
|
|
79
|
+
assert ["s1", "s2", "s3"] == r.sunion("{qux}foo", "{qux}bar").sort
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
test "SUNIONSTORE" do |r|
|
|
83
|
+
r.sadd "{qux}foo", "s1"
|
|
84
|
+
r.sadd "{qux}foo", "s2"
|
|
85
|
+
r.sadd "{qux}bar", "s2"
|
|
86
|
+
r.sadd "{qux}bar", "s3"
|
|
87
|
+
|
|
88
|
+
r.sunionstore("{qux}baz", "{qux}foo", "{qux}bar")
|
|
89
|
+
|
|
90
|
+
assert ["s1", "s2", "s3"] == r.smembers("{qux}baz").sort
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
test "SDIFF" do |r|
|
|
94
|
+
r.sadd "{qux}foo", "s1"
|
|
95
|
+
r.sadd "{qux}foo", "s2"
|
|
96
|
+
r.sadd "{qux}bar", "s2"
|
|
97
|
+
r.sadd "{qux}bar", "s3"
|
|
98
|
+
|
|
99
|
+
assert ["s1"] == r.sdiff("{qux}foo", "{qux}bar")
|
|
100
|
+
assert ["s3"] == r.sdiff("{qux}bar", "{qux}foo")
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
test "SDIFFSTORE" do |r|
|
|
104
|
+
r.sadd "{qux}foo", "s1"
|
|
105
|
+
r.sadd "{qux}foo", "s2"
|
|
106
|
+
r.sadd "{qux}bar", "s2"
|
|
107
|
+
r.sadd "{qux}bar", "s3"
|
|
108
|
+
|
|
109
|
+
r.sdiffstore("{qux}baz", "{qux}foo", "{qux}bar")
|
|
110
|
+
|
|
111
|
+
assert ["s1"] == r.smembers("{qux}baz")
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
test "SORT" do |r|
|
|
115
|
+
r.set("{qux}foo:1", "s1")
|
|
116
|
+
r.set("{qux}foo:2", "s2")
|
|
117
|
+
|
|
118
|
+
r.rpush("{qux}bar", "1")
|
|
119
|
+
r.rpush("{qux}bar", "2")
|
|
120
|
+
|
|
121
|
+
assert ["s1"] == r.sort("{qux}bar", :get => "{qux}foo:*", :limit => [0, 1])
|
|
122
|
+
assert ["s2"] == r.sort("{qux}bar", :get => "{qux}foo:*", :limit => [0, 1], :order => "desc alpha")
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
test "SORT with an array of GETs" do |r|
|
|
126
|
+
r.set("{qux}foo:1:a", "s1a")
|
|
127
|
+
r.set("{qux}foo:1:b", "s1b")
|
|
128
|
+
|
|
129
|
+
r.set("{qux}foo:2:a", "s2a")
|
|
130
|
+
r.set("{qux}foo:2:b", "s2b")
|
|
131
|
+
|
|
132
|
+
r.rpush("{qux}bar", "1")
|
|
133
|
+
r.rpush("{qux}bar", "2")
|
|
134
|
+
|
|
135
|
+
assert ["s1a", "s1b"] == r.sort("{qux}bar", :get => ["{qux}foo:*:a", "{qux}foo:*:b"], :limit => [0, 1])
|
|
136
|
+
assert ["s2a", "s2b"] == r.sort("{qux}bar", :get => ["{qux}foo:*:a", "{qux}foo:*:b"], :limit => [0, 1], :order => "desc alpha")
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
test "SORT with STORE" do |r|
|
|
140
|
+
r.set("{qux}foo:1", "s1")
|
|
141
|
+
r.set("{qux}foo:2", "s2")
|
|
142
|
+
|
|
143
|
+
r.rpush("{qux}bar", "1")
|
|
144
|
+
r.rpush("{qux}bar", "2")
|
|
145
|
+
|
|
146
|
+
r.sort("{qux}bar", :get => "{qux}foo:*", :store => "{qux}baz")
|
|
147
|
+
assert ["s1", "s2"] == r.lrange("{qux}baz", 0, -1)
|
|
148
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
require File.expand_path("./helper", File.dirname(__FILE__))
|
|
4
|
+
require "redis/distributed"
|
|
5
|
+
|
|
6
|
+
setup do
|
|
7
|
+
log = StringIO.new
|
|
8
|
+
init Redis::Distributed.new(NODES, :logger => ::Logger.new(log))
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
test "PING" do |r|
|
|
12
|
+
assert ["PONG"] == r.ping
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
test "SELECT" do |r|
|
|
16
|
+
r.set "foo", "bar"
|
|
17
|
+
|
|
18
|
+
r.select 14
|
|
19
|
+
assert nil == r.get("foo")
|
|
20
|
+
|
|
21
|
+
r.select 15
|
|
22
|
+
|
|
23
|
+
assert "bar" == r.get("foo")
|
|
24
|
+
end
|
|
25
|
+
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
require File.expand_path("./helper", File.dirname(__FILE__))
|
|
4
|
+
require File.expand_path("./redis_mock", File.dirname(__FILE__))
|
|
5
|
+
|
|
6
|
+
include RedisMock::Helper
|
|
7
|
+
|
|
8
|
+
require "redis/distributed"
|
|
9
|
+
|
|
10
|
+
setup do
|
|
11
|
+
log = StringIO.new
|
|
12
|
+
[init(Redis::Distributed.new(NODES, :logger => ::Logger.new(log))), log]
|
|
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
|
|
22
|
+
|
|
23
|
+
node_info = nodes.map do |node|
|
|
24
|
+
"#{node} (Redis v#{@r.info.first["redis_version"]})"
|
|
25
|
+
end
|
|
26
|
+
assert "#<Redis client v#{Redis::VERSION} connected to #{node_info.join(', ')}>" == @r.inspect
|
|
27
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
require File.expand_path("./helper", File.dirname(__FILE__))
|
|
4
|
+
require "redis/distributed"
|
|
5
|
+
|
|
6
|
+
setup do
|
|
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]
|
|
15
|
+
|
|
16
|
+
assert r1.node_for("foo").id == r2.node_for("foo").id
|
|
17
|
+
assert r1.node_for("foo").id == r3.node_for("foo").id
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
test "allows clustering of keys" do |r|
|
|
21
|
+
r = Redis::Distributed.new(NODES)
|
|
22
|
+
r.add_node("redis://localhost:6379/14")
|
|
23
|
+
r.flushdb
|
|
24
|
+
|
|
25
|
+
100.times do |i|
|
|
26
|
+
r.set "{foo}users:#{i}", i
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
assert [0, 100] == r.nodes.map { |node| node.keys.size }
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
test "distributes keys if no clustering is used" do |r|
|
|
33
|
+
r.add_node("redis://localhost:6379/14")
|
|
34
|
+
r.flushdb
|
|
35
|
+
|
|
36
|
+
r.set "users:1", 1
|
|
37
|
+
r.set "users:4", 4
|
|
38
|
+
|
|
39
|
+
assert [1, 1] == r.nodes.map { |node| node.keys.size }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
test "allows passing a custom tag extractor" do |r|
|
|
43
|
+
r = Redis::Distributed.new(NODES, :tag => /^(.+?):/)
|
|
44
|
+
r.add_node("redis://localhost:6379/14")
|
|
45
|
+
r.flushdb
|
|
46
|
+
|
|
47
|
+
100.times do |i|
|
|
48
|
+
r.set "foo:users:#{i}", i
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
assert [0, 100] == r.nodes.map { |node| node.keys.size }
|
|
52
|
+
end
|
|
53
|
+
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
require File.expand_path("./helper", File.dirname(__FILE__))
|
|
4
|
+
require "redis/distributed"
|
|
5
|
+
|
|
6
|
+
setup do
|
|
7
|
+
log = StringIO.new
|
|
8
|
+
init Redis::Distributed.new(NODES, :logger => ::Logger.new(log))
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
test "SAVE and BGSAVE" do |r|
|
|
12
|
+
assert_nothing_raised do
|
|
13
|
+
r.save
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
assert_nothing_raised do
|
|
17
|
+
r.bgsave
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
test "LASTSAVE" do |r|
|
|
22
|
+
assert r.lastsave.all? { |t| Time.at(t) <= Time.now }
|
|
23
|
+
end
|
|
24
|
+
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
require File.expand_path("./helper", File.dirname(__FILE__))
|
|
4
|
+
require "redis/distributed"
|
|
5
|
+
|
|
6
|
+
setup do
|
|
7
|
+
log = StringIO.new
|
|
8
|
+
init Redis::Distributed.new(NODES, :logger => ::Logger.new(log))
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
test "SUBSCRIBE and UNSUBSCRIBE" do |r|
|
|
12
|
+
assert_raise Redis::Distributed::CannotDistribute do
|
|
13
|
+
r.subscribe("foo", "bar") { }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
assert_raise Redis::Distributed::CannotDistribute do
|
|
17
|
+
r.subscribe("{qux}foo", "bar") { }
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
test "SUBSCRIBE and UNSUBSCRIBE with tags" do |r|
|
|
22
|
+
listening = false
|
|
23
|
+
|
|
24
|
+
wire = Wire.new do
|
|
25
|
+
r.subscribe("foo") do |on|
|
|
26
|
+
on.subscribe do |channel, total|
|
|
27
|
+
@subscribed = true
|
|
28
|
+
@t1 = total
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
on.message do |channel, message|
|
|
32
|
+
if message == "s1"
|
|
33
|
+
r.unsubscribe
|
|
34
|
+
@message = message
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
on.unsubscribe do |channel, total|
|
|
39
|
+
@unsubscribed = true
|
|
40
|
+
@t2 = total
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
listening = true
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
Wire.pass while !listening
|
|
48
|
+
|
|
49
|
+
Redis::Distributed.new(NODES).publish("foo", "s1")
|
|
50
|
+
|
|
51
|
+
wire.join
|
|
52
|
+
|
|
53
|
+
assert @subscribed
|
|
54
|
+
assert 1 == @t1
|
|
55
|
+
assert @unsubscribed
|
|
56
|
+
assert 0 == @t2
|
|
57
|
+
assert "s1" == @message
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
test "SUBSCRIBE within SUBSCRIBE" do |r|
|
|
61
|
+
listening = false
|
|
62
|
+
@channels = []
|
|
63
|
+
|
|
64
|
+
wire = Wire.new do
|
|
65
|
+
r.subscribe("foo") do |on|
|
|
66
|
+
on.subscribe do |channel, total|
|
|
67
|
+
@channels << channel
|
|
68
|
+
|
|
69
|
+
r.subscribe("bar") if channel == "foo"
|
|
70
|
+
r.unsubscribe if channel == "bar"
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
listening = true
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
Wire.pass while !listening
|
|
78
|
+
|
|
79
|
+
Redis::Distributed.new(NODES).publish("foo", "s1")
|
|
80
|
+
|
|
81
|
+
wire.join
|
|
82
|
+
|
|
83
|
+
assert ["foo", "bar"] == @channels
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
test "other commands within a SUBSCRIBE" do |r|
|
|
87
|
+
assert_raise RuntimeError do
|
|
88
|
+
r.subscribe("foo") do |on|
|
|
89
|
+
on.subscribe do |channel, total|
|
|
90
|
+
r.set("bar", "s2")
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
test "SUBSCRIBE without a block" do |r|
|
|
97
|
+
assert_raise LocalJumpError do
|
|
98
|
+
r.subscribe("foo")
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
require File.expand_path("./helper", File.dirname(__FILE__))
|
|
4
|
+
require "redis/distributed"
|
|
5
|
+
|
|
6
|
+
setup do
|
|
7
|
+
log = StringIO.new
|
|
8
|
+
init Redis::Distributed.new(NODES, :logger => ::Logger.new(log))
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
test "INFO" do |r|
|
|
12
|
+
%w(last_save_time redis_version total_connections_received connected_clients total_commands_processed connected_slaves uptime_in_seconds used_memory uptime_in_days changes_since_last_save).each do |x|
|
|
13
|
+
r.info.each do |info|
|
|
14
|
+
assert info.keys.include?(x)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
test "INFO COMMANDSTATS" do |r|
|
|
20
|
+
# Only available on Redis >= 2.3.0
|
|
21
|
+
next if r.info.first["redis_version"] < "2.3.0"
|
|
22
|
+
|
|
23
|
+
r.nodes.each { |n| n.config(:resetstat) }
|
|
24
|
+
r.ping # Executed on every node
|
|
25
|
+
|
|
26
|
+
r.info(:commandstats).each do |info|
|
|
27
|
+
assert "1" == info["ping"]["calls"]
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
test "MONITOR" do |r|
|
|
32
|
+
begin
|
|
33
|
+
r.monitor
|
|
34
|
+
rescue Exception => ex
|
|
35
|
+
ensure
|
|
36
|
+
assert ex.kind_of?(NotImplementedError)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
test "ECHO" do |r|
|
|
41
|
+
assert ["foo bar baz\n"] == r.echo("foo bar baz\n")
|
|
42
|
+
end
|
|
43
|
+
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
require File.expand_path("./helper", File.dirname(__FILE__))
|
|
4
|
+
require "redis/distributed"
|
|
5
|
+
|
|
6
|
+
setup do
|
|
7
|
+
log = StringIO.new
|
|
8
|
+
init Redis::Distributed.new(NODES, :logger => ::Logger.new(log))
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
test "SORT" do |r|
|
|
12
|
+
assert_raise Redis::Distributed::CannotDistribute do
|
|
13
|
+
r.set("foo:1", "s1")
|
|
14
|
+
r.set("foo:2", "s2")
|
|
15
|
+
|
|
16
|
+
r.rpush("bar", "1")
|
|
17
|
+
r.rpush("bar", "2")
|
|
18
|
+
|
|
19
|
+
r.sort("bar", :get => "foo:*", :limit => [0, 1])
|
|
20
|
+
end
|
|
21
|
+
end
|