redis 3.0.0 → 4.5.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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +315 -0
- data/README.md +301 -58
- data/lib/redis/client.rb +383 -88
- data/lib/redis/cluster/command.rb +81 -0
- data/lib/redis/cluster/command_loader.rb +33 -0
- data/lib/redis/cluster/key_slot_converter.rb +72 -0
- data/lib/redis/cluster/node.rb +108 -0
- data/lib/redis/cluster/node_key.rb +31 -0
- data/lib/redis/cluster/node_loader.rb +37 -0
- data/lib/redis/cluster/option.rb +93 -0
- data/lib/redis/cluster/slot.rb +86 -0
- data/lib/redis/cluster/slot_loader.rb +49 -0
- data/lib/redis/cluster.rb +291 -0
- data/lib/redis/connection/command_helper.rb +7 -10
- data/lib/redis/connection/hiredis.rb +12 -8
- data/lib/redis/connection/registry.rb +2 -1
- data/lib/redis/connection/ruby.rb +266 -74
- data/lib/redis/connection/synchrony.rb +41 -14
- data/lib/redis/connection.rb +4 -2
- data/lib/redis/distributed.rb +258 -76
- data/lib/redis/errors.rb +48 -0
- data/lib/redis/hash_ring.rb +31 -73
- data/lib/redis/pipeline.rb +74 -18
- data/lib/redis/subscribe.rb +24 -13
- data/lib/redis/version.rb +3 -1
- data/lib/redis.rb +2068 -464
- metadata +63 -160
- data/.gitignore +0 -10
- data/.order +0 -169
- data/.travis/Gemfile +0 -11
- data/.travis.yml +0 -50
- data/.yardopts +0 -3
- data/Rakefile +0 -392
- data/benchmarking/logging.rb +0 -62
- data/benchmarking/pipeline.rb +0 -51
- data/benchmarking/speed.rb +0 -21
- data/benchmarking/suite.rb +0 -24
- data/benchmarking/worker.rb +0 -71
- data/examples/basic.rb +0 -15
- data/examples/dist_redis.rb +0 -43
- data/examples/incr-decr.rb +0 -17
- data/examples/list.rb +0 -26
- data/examples/pubsub.rb +0 -31
- data/examples/sets.rb +0 -36
- data/examples/unicorn/config.ru +0 -3
- data/examples/unicorn/unicorn.rb +0 -20
- data/redis.gemspec +0 -41
- data/test/blocking_commands_test.rb +0 -42
- data/test/command_map_test.rb +0 -30
- data/test/commands_on_hashes_test.rb +0 -21
- data/test/commands_on_lists_test.rb +0 -20
- data/test/commands_on_sets_test.rb +0 -77
- data/test/commands_on_sorted_sets_test.rb +0 -109
- data/test/commands_on_strings_test.rb +0 -83
- data/test/commands_on_value_types_test.rb +0 -99
- data/test/connection_handling_test.rb +0 -189
- data/test/db/.gitignore +0 -1
- data/test/distributed_blocking_commands_test.rb +0 -46
- data/test/distributed_commands_on_hashes_test.rb +0 -10
- data/test/distributed_commands_on_lists_test.rb +0 -22
- data/test/distributed_commands_on_sets_test.rb +0 -83
- data/test/distributed_commands_on_sorted_sets_test.rb +0 -18
- data/test/distributed_commands_on_strings_test.rb +0 -48
- data/test/distributed_commands_on_value_types_test.rb +0 -87
- data/test/distributed_commands_requiring_clustering_test.rb +0 -148
- data/test/distributed_connection_handling_test.rb +0 -23
- data/test/distributed_internals_test.rb +0 -15
- data/test/distributed_key_tags_test.rb +0 -52
- data/test/distributed_persistence_control_commands_test.rb +0 -26
- data/test/distributed_publish_subscribe_test.rb +0 -92
- data/test/distributed_remote_server_control_commands_test.rb +0 -53
- data/test/distributed_scripting_test.rb +0 -102
- data/test/distributed_sorting_test.rb +0 -20
- data/test/distributed_test.rb +0 -58
- data/test/distributed_transactions_test.rb +0 -32
- data/test/encoding_test.rb +0 -18
- data/test/error_replies_test.rb +0 -59
- data/test/helper.rb +0 -188
- data/test/helper_test.rb +0 -22
- data/test/internals_test.rb +0 -214
- data/test/lint/blocking_commands.rb +0 -124
- data/test/lint/hashes.rb +0 -162
- data/test/lint/lists.rb +0 -143
- data/test/lint/sets.rb +0 -96
- data/test/lint/sorted_sets.rb +0 -201
- data/test/lint/strings.rb +0 -157
- data/test/lint/value_types.rb +0 -106
- data/test/persistence_control_commands_test.rb +0 -26
- data/test/pipelining_commands_test.rb +0 -195
- data/test/publish_subscribe_test.rb +0 -153
- data/test/remote_server_control_commands_test.rb +0 -104
- data/test/scripting_test.rb +0 -78
- data/test/sorting_test.rb +0 -45
- data/test/support/connection/hiredis.rb +0 -1
- data/test/support/connection/ruby.rb +0 -1
- data/test/support/connection/synchrony.rb +0 -17
- data/test/support/redis_mock.rb +0 -92
- data/test/support/wire/synchrony.rb +0 -24
- data/test/support/wire/thread.rb +0 -5
- data/test/synchrony_driver.rb +0 -57
- data/test/test.conf +0 -9
- data/test/thread_safety_test.rb +0 -32
- data/test/transactions_test.rb +0 -244
- data/test/unknown_commands_test.rb +0 -14
- data/test/url_param_test.rb +0 -64
@@ -1,24 +0,0 @@
|
|
1
|
-
class Wire < Fiber
|
2
|
-
# We cannot run this fiber explicitly because EM schedules it. Resuming the
|
3
|
-
# current fiber on the next tick to let the reactor do work.
|
4
|
-
def self.pass
|
5
|
-
f = Fiber.current
|
6
|
-
EM.next_tick { f.resume }
|
7
|
-
Fiber.yield
|
8
|
-
end
|
9
|
-
|
10
|
-
def self.sleep(sec)
|
11
|
-
EM::Synchrony.sleep(sec)
|
12
|
-
end
|
13
|
-
|
14
|
-
def initialize(&blk)
|
15
|
-
super
|
16
|
-
|
17
|
-
# Schedule run in next tick
|
18
|
-
EM.next_tick { resume }
|
19
|
-
end
|
20
|
-
|
21
|
-
def join
|
22
|
-
self.class.pass while alive?
|
23
|
-
end
|
24
|
-
end
|
data/test/support/wire/thread.rb
DELETED
data/test/synchrony_driver.rb
DELETED
@@ -1,57 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
|
-
require 'em-synchrony'
|
4
|
-
|
5
|
-
require 'redis'
|
6
|
-
require 'redis/connection/synchrony'
|
7
|
-
|
8
|
-
require File.expand_path("./helper", File.dirname(__FILE__))
|
9
|
-
|
10
|
-
#
|
11
|
-
# if running under Eventmachine + Synchrony (Ruby 1.9+), then
|
12
|
-
# we can simulate the blocking API while performing the network
|
13
|
-
# IO via the EM reactor.
|
14
|
-
#
|
15
|
-
|
16
|
-
EM.synchrony do
|
17
|
-
r = Redis.new
|
18
|
-
r.flushdb
|
19
|
-
|
20
|
-
r.rpush "foo", "s1"
|
21
|
-
r.rpush "foo", "s2"
|
22
|
-
|
23
|
-
assert_equal 2, r.llen("foo")
|
24
|
-
assert_equal "s2", r.rpop("foo")
|
25
|
-
|
26
|
-
r.set("foo", "bar")
|
27
|
-
|
28
|
-
assert_equal "bar", r.getset("foo", "baz")
|
29
|
-
assert_equal "baz", r.get("foo")
|
30
|
-
|
31
|
-
r.set("foo", "a")
|
32
|
-
|
33
|
-
assert_equal 1, r.getbit("foo", 1)
|
34
|
-
assert_equal 1, r.getbit("foo", 2)
|
35
|
-
assert_equal 0, r.getbit("foo", 3)
|
36
|
-
assert_equal 0, r.getbit("foo", 4)
|
37
|
-
assert_equal 0, r.getbit("foo", 5)
|
38
|
-
assert_equal 0, r.getbit("foo", 6)
|
39
|
-
assert_equal 1, r.getbit("foo", 7)
|
40
|
-
|
41
|
-
r.flushdb
|
42
|
-
|
43
|
-
# command pipelining
|
44
|
-
r.pipelined do
|
45
|
-
r.lpush "foo", "s1"
|
46
|
-
r.lpush "foo", "s2"
|
47
|
-
end
|
48
|
-
|
49
|
-
assert_equal 2, r.llen("foo")
|
50
|
-
assert_equal "s2", r.lpop("foo")
|
51
|
-
assert_equal "s1", r.lpop("foo")
|
52
|
-
|
53
|
-
assert_equal "OK", r.client.call(:quit)
|
54
|
-
assert_equal "PONG", r.ping
|
55
|
-
|
56
|
-
EM.stop
|
57
|
-
end
|
data/test/test.conf
DELETED
data/test/thread_safety_test.rb
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
|
-
require "helper"
|
4
|
-
|
5
|
-
class TestThreadSafety < Test::Unit::TestCase
|
6
|
-
|
7
|
-
include Helper::Client
|
8
|
-
|
9
|
-
driver(:ruby, :hiredis) do
|
10
|
-
def test_thread_safety
|
11
|
-
redis = Redis.new(OPTIONS)
|
12
|
-
redis.set "foo", 1
|
13
|
-
redis.set "bar", 2
|
14
|
-
|
15
|
-
sample = 100
|
16
|
-
|
17
|
-
t1 = Thread.new do
|
18
|
-
$foos = Array.new(sample) { redis.get "foo" }
|
19
|
-
end
|
20
|
-
|
21
|
-
t2 = Thread.new do
|
22
|
-
$bars = Array.new(sample) { redis.get "bar" }
|
23
|
-
end
|
24
|
-
|
25
|
-
t1.join
|
26
|
-
t2.join
|
27
|
-
|
28
|
-
assert_equal ["1"], $foos.uniq
|
29
|
-
assert_equal ["2"], $bars.uniq
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
data/test/transactions_test.rb
DELETED
@@ -1,244 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
|
-
require "helper"
|
4
|
-
|
5
|
-
class TestTransactions < Test::Unit::TestCase
|
6
|
-
|
7
|
-
include Helper::Client
|
8
|
-
|
9
|
-
def test_multi_discard
|
10
|
-
r.multi
|
11
|
-
|
12
|
-
assert_equal "QUEUED", r.set("foo", "1")
|
13
|
-
assert_equal "QUEUED", r.get("foo")
|
14
|
-
|
15
|
-
r.discard
|
16
|
-
|
17
|
-
assert_equal nil, r.get("foo")
|
18
|
-
end
|
19
|
-
|
20
|
-
def test_multi_exec_with_a_block
|
21
|
-
r.multi do |multi|
|
22
|
-
multi.set "foo", "s1"
|
23
|
-
end
|
24
|
-
|
25
|
-
assert_equal "s1", r.get("foo")
|
26
|
-
end
|
27
|
-
|
28
|
-
def test_multi_exec_with_a_block_doesn_t_return_replies_for_multi_and_exec
|
29
|
-
r1, r2, nothing_else = r.multi do |multi|
|
30
|
-
multi.set "foo", "s1"
|
31
|
-
multi.get "foo"
|
32
|
-
end
|
33
|
-
|
34
|
-
assert_equal "OK", r1
|
35
|
-
assert_equal "s1", r2
|
36
|
-
assert_equal nil, nothing_else
|
37
|
-
end
|
38
|
-
|
39
|
-
def test_assignment_inside_multi_exec_block
|
40
|
-
r.multi do |m|
|
41
|
-
@first = m.sadd("foo", 1)
|
42
|
-
@second = m.sadd("foo", 1)
|
43
|
-
end
|
44
|
-
|
45
|
-
assert_equal true, @first.value
|
46
|
-
assert_equal false, @second.value
|
47
|
-
end
|
48
|
-
|
49
|
-
# Although we could support accessing the values in these futures,
|
50
|
-
# it doesn't make a lot of sense.
|
51
|
-
def test_assignment_inside_multi_exec_block_with_delayed_command_errors
|
52
|
-
assert_raise(Redis::CommandError) do
|
53
|
-
r.multi do |m|
|
54
|
-
@first = m.set("foo", "s1")
|
55
|
-
@second = m.incr("foo") # not an integer
|
56
|
-
@third = m.lpush("foo", "value") # wrong kind of value
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
assert_equal "OK", @first.value
|
61
|
-
assert_raise(Redis::CommandError) { @second.value }
|
62
|
-
assert_raise(Redis::FutureNotReady) { @third.value }
|
63
|
-
end
|
64
|
-
|
65
|
-
def test_assignment_inside_multi_exec_block_with_immediate_command_errors
|
66
|
-
assert_raise(Redis::CommandError) do
|
67
|
-
r.multi do |m|
|
68
|
-
m.doesnt_exist
|
69
|
-
@first = m.sadd("foo", 1)
|
70
|
-
m.doesnt_exist
|
71
|
-
@second = m.sadd("foo", 1)
|
72
|
-
m.doesnt_exist
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
assert_raise(Redis::FutureNotReady) { @first.value }
|
77
|
-
assert_raise(Redis::FutureNotReady) { @second.value }
|
78
|
-
end
|
79
|
-
|
80
|
-
def test_raise_immediate_errors_in_multi_exec
|
81
|
-
assert_raise(RuntimeError) do
|
82
|
-
r.multi do |multi|
|
83
|
-
multi.set "bar", "s2"
|
84
|
-
raise "Some error"
|
85
|
-
multi.set "baz", "s3"
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
assert_equal nil, r.get("bar")
|
90
|
-
assert_equal nil, r.get("baz")
|
91
|
-
end
|
92
|
-
|
93
|
-
def test_transformed_replies_as_return_values_for_multi_exec_block
|
94
|
-
info, _ = r.multi do |m|
|
95
|
-
r.info
|
96
|
-
end
|
97
|
-
|
98
|
-
assert info.kind_of?(Hash)
|
99
|
-
end
|
100
|
-
|
101
|
-
def test_transformed_replies_inside_multi_exec_block
|
102
|
-
r.multi do |m|
|
103
|
-
@info = r.info
|
104
|
-
end
|
105
|
-
|
106
|
-
assert @info.value.kind_of?(Hash)
|
107
|
-
end
|
108
|
-
|
109
|
-
def test_raise_command_errors_in_multi_exec
|
110
|
-
assert_raise(Redis::CommandError) do
|
111
|
-
r.multi do |m|
|
112
|
-
m.set("foo", "s1")
|
113
|
-
m.incr("foo") # not an integer
|
114
|
-
m.lpush("foo", "value") # wrong kind of value
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
assert_equal "s1", r.get("foo")
|
119
|
-
end
|
120
|
-
|
121
|
-
def test_raise_command_errors_when_accessing_futures_after_multi_exec
|
122
|
-
begin
|
123
|
-
r.multi do |m|
|
124
|
-
m.set("foo", "s1")
|
125
|
-
@counter = m.incr("foo") # not an integer
|
126
|
-
end
|
127
|
-
rescue Exception
|
128
|
-
# Not gonna deal with it
|
129
|
-
end
|
130
|
-
|
131
|
-
# We should test for Redis::Error here, but hiredis doesn't yet do
|
132
|
-
# custom error classes.
|
133
|
-
err = nil
|
134
|
-
begin
|
135
|
-
@counter.value
|
136
|
-
rescue => err
|
137
|
-
end
|
138
|
-
|
139
|
-
assert err.kind_of?(RuntimeError)
|
140
|
-
end
|
141
|
-
|
142
|
-
def test_multi_with_a_block_yielding_the_client
|
143
|
-
r.multi do |multi|
|
144
|
-
multi.set "foo", "s1"
|
145
|
-
end
|
146
|
-
|
147
|
-
assert_equal "s1", r.get("foo")
|
148
|
-
end
|
149
|
-
|
150
|
-
def test_watch_with_an_unmodified_key
|
151
|
-
r.watch "foo"
|
152
|
-
r.multi do |multi|
|
153
|
-
multi.set "foo", "s1"
|
154
|
-
end
|
155
|
-
|
156
|
-
assert_equal "s1", r.get("foo")
|
157
|
-
end
|
158
|
-
|
159
|
-
def test_watch_with_an_unmodified_key_passed_as_array
|
160
|
-
r.watch ["foo", "bar"]
|
161
|
-
r.multi do |multi|
|
162
|
-
multi.set "foo", "s1"
|
163
|
-
end
|
164
|
-
|
165
|
-
assert_equal "s1", r.get("foo")
|
166
|
-
end
|
167
|
-
|
168
|
-
def test_watch_with_a_modified_key
|
169
|
-
r.watch "foo"
|
170
|
-
r.set "foo", "s1"
|
171
|
-
res = r.multi do |multi|
|
172
|
-
multi.set "foo", "s2"
|
173
|
-
end
|
174
|
-
|
175
|
-
assert_equal nil, res
|
176
|
-
assert_equal "s1", r.get("foo")
|
177
|
-
end
|
178
|
-
|
179
|
-
def test_watch_with_a_modified_key_passed_as_array
|
180
|
-
r.watch ["foo", "bar"]
|
181
|
-
r.set "foo", "s1"
|
182
|
-
res = r.multi do |multi|
|
183
|
-
multi.set "foo", "s2"
|
184
|
-
end
|
185
|
-
|
186
|
-
assert_equal nil, res
|
187
|
-
assert_equal "s1", r.get("foo")
|
188
|
-
end
|
189
|
-
|
190
|
-
def test_watch_with_a_block_and_an_unmodified_key
|
191
|
-
result = r.watch "foo" do
|
192
|
-
r.multi do |multi|
|
193
|
-
multi.set "foo", "s1"
|
194
|
-
end
|
195
|
-
end
|
196
|
-
|
197
|
-
assert_equal ["OK"], result
|
198
|
-
assert_equal "s1", r.get("foo")
|
199
|
-
end
|
200
|
-
|
201
|
-
def test_watch_with_a_block_and_a_modified_key
|
202
|
-
result = r.watch "foo" do
|
203
|
-
r.set "foo", "s1"
|
204
|
-
r.multi do |multi|
|
205
|
-
multi.set "foo", "s2"
|
206
|
-
end
|
207
|
-
end
|
208
|
-
|
209
|
-
assert_equal nil, result
|
210
|
-
assert_equal "s1", r.get("foo")
|
211
|
-
end
|
212
|
-
|
213
|
-
def test_watch_with_a_block_that_raises_an_exception
|
214
|
-
r.set("foo", "s1")
|
215
|
-
|
216
|
-
begin
|
217
|
-
r.watch "foo" do
|
218
|
-
raise "test"
|
219
|
-
end
|
220
|
-
rescue RuntimeError
|
221
|
-
end
|
222
|
-
|
223
|
-
r.set("foo", "s2")
|
224
|
-
|
225
|
-
# If the watch was still set from within the block above, this multi/exec
|
226
|
-
# would fail. This proves that raising an exception above unwatches.
|
227
|
-
r.multi do |multi|
|
228
|
-
multi.set "foo", "s3"
|
229
|
-
end
|
230
|
-
|
231
|
-
assert_equal "s3", r.get("foo")
|
232
|
-
end
|
233
|
-
|
234
|
-
def test_unwatch_with_a_modified_key
|
235
|
-
r.watch "foo"
|
236
|
-
r.set "foo", "s1"
|
237
|
-
r.unwatch
|
238
|
-
r.multi do |multi|
|
239
|
-
multi.set "foo", "s2"
|
240
|
-
end
|
241
|
-
|
242
|
-
assert_equal "s2", r.get("foo")
|
243
|
-
end
|
244
|
-
end
|
data/test/url_param_test.rb
DELETED
@@ -1,64 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
|
-
require "helper"
|
4
|
-
|
5
|
-
class TestUrlParam < Test::Unit::TestCase
|
6
|
-
|
7
|
-
include Helper::Client
|
8
|
-
|
9
|
-
def test_url_defaults_to_______________
|
10
|
-
redis = Redis.new
|
11
|
-
|
12
|
-
assert_equal "127.0.0.1", redis.client.host
|
13
|
-
assert_equal 6379, redis.client.port
|
14
|
-
assert_equal 0, redis.client.db
|
15
|
-
assert_equal nil, redis.client.password
|
16
|
-
end
|
17
|
-
|
18
|
-
def test_allows_to_pass_in_a_url
|
19
|
-
redis = Redis.new :url => "redis://:secr3t@foo.com:999/2"
|
20
|
-
|
21
|
-
assert_equal "foo.com", redis.client.host
|
22
|
-
assert_equal 999, redis.client.port
|
23
|
-
assert_equal 2, redis.client.db
|
24
|
-
assert_equal "secr3t", redis.client.password
|
25
|
-
end
|
26
|
-
|
27
|
-
def test_override_url_if_path_option_is_passed
|
28
|
-
redis = Redis.new :url => "redis://:secr3t@foo.com/foo:999/2", :path => "/tmp/redis.sock"
|
29
|
-
|
30
|
-
assert_equal "/tmp/redis.sock", redis.client.path
|
31
|
-
assert_equal nil, redis.client.host
|
32
|
-
assert_equal nil, redis.client.port
|
33
|
-
end
|
34
|
-
|
35
|
-
def test_overrides_url_if_another_connection_option_is_passed
|
36
|
-
redis = Redis.new :url => "redis://:secr3t@foo.com:999/2", :port => 1000
|
37
|
-
|
38
|
-
assert_equal "foo.com", redis.client.host
|
39
|
-
assert_equal 1000, redis.client.port
|
40
|
-
assert_equal 2, redis.client.db
|
41
|
-
assert_equal "secr3t", redis.client.password
|
42
|
-
end
|
43
|
-
|
44
|
-
def test_does_not_modify_the_passed_options
|
45
|
-
options = { :url => "redis://:secr3t@foo.com:999/2" }
|
46
|
-
|
47
|
-
Redis.new(options)
|
48
|
-
|
49
|
-
assert({ :url => "redis://:secr3t@foo.com:999/2" } == options)
|
50
|
-
end
|
51
|
-
|
52
|
-
def test_uses_redis_url_over_default_if_available
|
53
|
-
ENV["REDIS_URL"] = "redis://:secr3t@foo.com:999/2"
|
54
|
-
|
55
|
-
redis = Redis.new
|
56
|
-
|
57
|
-
assert_equal "foo.com", redis.client.host
|
58
|
-
assert_equal 999, redis.client.port
|
59
|
-
assert_equal 2, redis.client.db
|
60
|
-
assert_equal "secr3t", redis.client.password
|
61
|
-
|
62
|
-
ENV.delete("REDIS_URL")
|
63
|
-
end
|
64
|
-
end
|