redis 4.0.0.rc1 → 4.5.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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +164 -3
- data/README.md +127 -18
- data/lib/redis/client.rb +164 -93
- 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 +5 -2
- data/lib/redis/connection/hiredis.rb +4 -3
- data/lib/redis/connection/registry.rb +2 -1
- data/lib/redis/connection/ruby.rb +125 -106
- data/lib/redis/connection/synchrony.rb +18 -5
- data/lib/redis/connection.rb +2 -0
- data/lib/redis/distributed.rb +995 -0
- data/lib/redis/errors.rb +48 -0
- data/lib/redis/hash_ring.rb +89 -0
- data/lib/redis/pipeline.rb +55 -9
- data/lib/redis/subscribe.rb +11 -12
- data/lib/redis/version.rb +3 -1
- data/lib/redis.rb +1433 -381
- metadata +34 -141
- data/.gitignore +0 -16
- data/.travis/Gemfile +0 -11
- data/.travis.yml +0 -71
- data/.yardopts +0 -3
- data/Gemfile +0 -3
- data/benchmarking/logging.rb +0 -71
- 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/consistency.rb +0 -114
- data/examples/incr-decr.rb +0 -17
- data/examples/list.rb +0 -26
- data/examples/pubsub.rb +0 -37
- data/examples/sentinel/sentinel.conf +0 -9
- data/examples/sentinel/start +0 -49
- data/examples/sentinel.rb +0 -41
- data/examples/sets.rb +0 -36
- data/examples/unicorn/config.ru +0 -3
- data/examples/unicorn/unicorn.rb +0 -20
- data/makefile +0 -42
- data/redis.gemspec +0 -40
- data/test/bitpos_test.rb +0 -63
- data/test/blocking_commands_test.rb +0 -183
- data/test/client_test.rb +0 -59
- data/test/command_map_test.rb +0 -28
- data/test/commands_on_hashes_test.rb +0 -174
- data/test/commands_on_hyper_log_log_test.rb +0 -70
- data/test/commands_on_lists_test.rb +0 -154
- data/test/commands_on_sets_test.rb +0 -208
- data/test/commands_on_sorted_sets_test.rb +0 -444
- data/test/commands_on_strings_test.rb +0 -338
- data/test/commands_on_value_types_test.rb +0 -246
- data/test/connection_handling_test.rb +0 -275
- data/test/db/.gitkeep +0 -0
- data/test/encoding_test.rb +0 -14
- data/test/error_replies_test.rb +0 -57
- data/test/fork_safety_test.rb +0 -60
- data/test/helper.rb +0 -179
- data/test/helper_test.rb +0 -22
- data/test/internals_test.rb +0 -435
- data/test/persistence_control_commands_test.rb +0 -24
- data/test/pipelining_commands_test.rb +0 -238
- data/test/publish_subscribe_test.rb +0 -280
- data/test/remote_server_control_commands_test.rb +0 -175
- data/test/scanning_test.rb +0 -407
- data/test/scripting_test.rb +0 -76
- data/test/sentinel_command_test.rb +0 -78
- data/test/sentinel_test.rb +0 -253
- data/test/sorting_test.rb +0 -57
- data/test/ssl_test.rb +0 -69
- 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 -130
- data/test/support/ssl/gen_certs.sh +0 -31
- data/test/support/ssl/trusted-ca.crt +0 -25
- data/test/support/ssl/trusted-ca.key +0 -27
- data/test/support/ssl/trusted-cert.crt +0 -81
- data/test/support/ssl/trusted-cert.key +0 -28
- data/test/support/ssl/untrusted-ca.crt +0 -26
- data/test/support/ssl/untrusted-ca.key +0 -27
- data/test/support/ssl/untrusted-cert.crt +0 -82
- data/test/support/ssl/untrusted-cert.key +0 -28
- data/test/support/wire/synchrony.rb +0 -24
- data/test/support/wire/thread.rb +0 -5
- data/test/synchrony_driver.rb +0 -85
- data/test/test.conf.erb +0 -9
- data/test/thread_safety_test.rb +0 -60
- data/test/transactions_test.rb +0 -262
- data/test/unknown_commands_test.rb +0 -12
- data/test/url_param_test.rb +0 -136
@@ -1,7 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Redis
|
2
4
|
module Connection
|
3
5
|
module CommandHelper
|
4
|
-
|
5
6
|
COMMAND_DELIMITER = "\r\n"
|
6
7
|
|
7
8
|
def build_command(args)
|
@@ -11,11 +12,13 @@ class Redis
|
|
11
12
|
if i.is_a? Array
|
12
13
|
i.each do |j|
|
13
14
|
j = j.to_s
|
15
|
+
j = j.encoding == Encoding::BINARY ? j : j.b
|
14
16
|
command << "$#{j.bytesize}"
|
15
17
|
command << j
|
16
18
|
end
|
17
19
|
else
|
18
20
|
i = i.to_s
|
21
|
+
i = i.encoding == Encoding::BINARY ? i : i.b
|
19
22
|
command << "$#{i.bytesize}"
|
20
23
|
command << i
|
21
24
|
end
|
@@ -28,7 +31,7 @@ class Redis
|
|
28
31
|
command.join(COMMAND_DELIMITER)
|
29
32
|
end
|
30
33
|
|
31
|
-
|
34
|
+
protected
|
32
35
|
|
33
36
|
def encode(string)
|
34
37
|
string.force_encoding(Encoding.default_external)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative "registry"
|
2
4
|
require_relative "../errors"
|
3
5
|
require "hiredis/connection"
|
@@ -6,7 +8,6 @@ require "timeout"
|
|
6
8
|
class Redis
|
7
9
|
module Connection
|
8
10
|
class Hiredis
|
9
|
-
|
10
11
|
def self.connect(config)
|
11
12
|
connection = ::Hiredis::Connection.new
|
12
13
|
connect_timeout = (config.fetch(:connect_timeout, 0) * 1_000_000).to_i
|
@@ -31,7 +32,7 @@ class Redis
|
|
31
32
|
end
|
32
33
|
|
33
34
|
def connected?
|
34
|
-
@connection
|
35
|
+
@connection&.connected?
|
35
36
|
end
|
36
37
|
|
37
38
|
def timeout=(timeout)
|
@@ -57,7 +58,7 @@ class Redis
|
|
57
58
|
rescue Errno::EAGAIN
|
58
59
|
raise TimeoutError
|
59
60
|
rescue RuntimeError => err
|
60
|
-
raise ProtocolError
|
61
|
+
raise ProtocolError, err.message
|
61
62
|
end
|
62
63
|
end
|
63
64
|
end
|
@@ -1,6 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class Redis
|
2
4
|
module Connection
|
3
|
-
|
4
5
|
# Store a list of loaded connection drivers in the Connection module.
|
5
6
|
# Redis::Client uses the last required driver by default, and will be aware
|
6
7
|
# of the loaded connection drivers if the user chooses to override the
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative "registry"
|
2
4
|
require_relative "command_helper"
|
3
5
|
require_relative "../errors"
|
@@ -13,108 +15,85 @@ end
|
|
13
15
|
class Redis
|
14
16
|
module Connection
|
15
17
|
module SocketMixin
|
16
|
-
|
17
|
-
CRLF = "\r\n".freeze
|
18
|
+
CRLF = "\r\n"
|
18
19
|
|
19
20
|
def initialize(*args)
|
20
21
|
super(*args)
|
21
22
|
|
22
23
|
@timeout = @write_timeout = nil
|
23
|
-
@buffer = ""
|
24
|
+
@buffer = "".b
|
24
25
|
end
|
25
26
|
|
26
27
|
def timeout=(timeout)
|
27
|
-
if timeout && timeout > 0
|
28
|
-
@timeout = timeout
|
29
|
-
else
|
30
|
-
@timeout = nil
|
31
|
-
end
|
28
|
+
@timeout = (timeout if timeout && timeout > 0)
|
32
29
|
end
|
33
30
|
|
34
31
|
def write_timeout=(timeout)
|
35
|
-
if timeout && timeout > 0
|
36
|
-
@write_timeout = timeout
|
37
|
-
else
|
38
|
-
@write_timeout = nil
|
39
|
-
end
|
32
|
+
@write_timeout = (timeout if timeout && timeout > 0)
|
40
33
|
end
|
41
34
|
|
42
35
|
def read(nbytes)
|
43
36
|
result = @buffer.slice!(0, nbytes)
|
44
37
|
|
45
|
-
|
46
|
-
|
47
|
-
end
|
38
|
+
buffer = String.new(capacity: nbytes, encoding: Encoding::ASCII_8BIT)
|
39
|
+
result << _read_from_socket(nbytes - result.bytesize, buffer) while result.bytesize < nbytes
|
48
40
|
|
49
41
|
result
|
50
42
|
end
|
51
43
|
|
52
44
|
def gets
|
53
|
-
crlf = nil
|
54
|
-
|
55
|
-
while (crlf = @buffer.index(CRLF)) == nil
|
56
|
-
@buffer << _read_from_socket(1024)
|
45
|
+
while (crlf = @buffer.index(CRLF)).nil?
|
46
|
+
@buffer << _read_from_socket(16_384)
|
57
47
|
end
|
58
48
|
|
59
49
|
@buffer.slice!(0, crlf + CRLF.bytesize)
|
60
50
|
end
|
61
51
|
|
62
|
-
def _read_from_socket(nbytes)
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
raise Redis::TimeoutError
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
rescue EOFError
|
82
|
-
raise Errno::ECONNRESET
|
83
|
-
end
|
84
|
-
|
85
|
-
def _write_to_socket(data)
|
86
|
-
begin
|
87
|
-
write_nonblock(data)
|
88
|
-
|
89
|
-
rescue IO::WaitWritable
|
90
|
-
if IO.select(nil, [self], nil, @write_timeout)
|
91
|
-
retry
|
92
|
-
else
|
93
|
-
raise Redis::TimeoutError
|
94
|
-
end
|
95
|
-
rescue IO::WaitReadable
|
96
|
-
if IO.select([self], nil, nil, @write_timeout)
|
97
|
-
retry
|
98
|
-
else
|
99
|
-
raise Redis::TimeoutError
|
52
|
+
def _read_from_socket(nbytes, buffer = nil)
|
53
|
+
loop do
|
54
|
+
case chunk = read_nonblock(nbytes, buffer, exception: false)
|
55
|
+
when :wait_readable
|
56
|
+
unless wait_readable(@timeout)
|
57
|
+
raise Redis::TimeoutError
|
58
|
+
end
|
59
|
+
when :wait_writable
|
60
|
+
unless wait_writable(@timeout)
|
61
|
+
raise Redis::TimeoutError
|
62
|
+
end
|
63
|
+
when nil
|
64
|
+
raise Errno::ECONNRESET
|
65
|
+
when String
|
66
|
+
return chunk
|
100
67
|
end
|
101
68
|
end
|
102
|
-
|
103
|
-
rescue EOFError
|
104
|
-
raise Errno::ECONNRESET
|
105
69
|
end
|
106
70
|
|
107
|
-
def write(
|
108
|
-
return super(
|
71
|
+
def write(buffer)
|
72
|
+
return super(buffer) unless @write_timeout
|
109
73
|
|
110
|
-
|
111
|
-
|
74
|
+
bytes_to_write = buffer.bytesize
|
75
|
+
total_bytes_written = 0
|
112
76
|
loop do
|
113
|
-
|
77
|
+
case bytes_written = write_nonblock(buffer, exception: false)
|
78
|
+
when :wait_readable
|
79
|
+
unless wait_readable(@write_timeout)
|
80
|
+
raise Redis::TimeoutError
|
81
|
+
end
|
82
|
+
when :wait_writable
|
83
|
+
unless wait_writable(@write_timeout)
|
84
|
+
raise Redis::TimeoutError
|
85
|
+
end
|
86
|
+
when nil
|
87
|
+
raise Errno::ECONNRESET
|
88
|
+
when Integer
|
89
|
+
total_bytes_written += bytes_written
|
90
|
+
|
91
|
+
if total_bytes_written >= bytes_to_write
|
92
|
+
return total_bytes_written
|
93
|
+
end
|
114
94
|
|
115
|
-
|
116
|
-
|
117
|
-
data = data.byteslice(count..-1)
|
95
|
+
buffer = buffer.byteslice(bytes_written..-1)
|
96
|
+
end
|
118
97
|
end
|
119
98
|
end
|
120
99
|
end
|
@@ -124,7 +103,6 @@ class Redis
|
|
124
103
|
require "timeout"
|
125
104
|
|
126
105
|
class TCPSocket < ::TCPSocket
|
127
|
-
|
128
106
|
include SocketMixin
|
129
107
|
|
130
108
|
def self.connect(host, port, timeout)
|
@@ -140,7 +118,6 @@ class Redis
|
|
140
118
|
if defined?(::UNIXSocket)
|
141
119
|
|
142
120
|
class UNIXSocket < ::UNIXSocket
|
143
|
-
|
144
121
|
include SocketMixin
|
145
122
|
|
146
123
|
def self.connect(path, timeout)
|
@@ -152,13 +129,12 @@ class Redis
|
|
152
129
|
raise TimeoutError
|
153
130
|
end
|
154
131
|
|
155
|
-
# JRuby raises Errno::EAGAIN on #read_nonblock even when
|
132
|
+
# JRuby raises Errno::EAGAIN on #read_nonblock even when it
|
156
133
|
# says it is readable (1.6.6, in both 1.8 and 1.9 mode).
|
157
134
|
# Use the blocking #readpartial method instead.
|
158
135
|
|
159
136
|
def _read_from_socket(nbytes)
|
160
137
|
readpartial(nbytes)
|
161
|
-
|
162
138
|
rescue EOFError
|
163
139
|
raise Errno::ECONNRESET
|
164
140
|
end
|
@@ -169,19 +145,16 @@ class Redis
|
|
169
145
|
else
|
170
146
|
|
171
147
|
class TCPSocket < ::Socket
|
172
|
-
|
173
148
|
include SocketMixin
|
174
149
|
|
175
|
-
def self.connect_addrinfo(
|
176
|
-
sock = new(::Socket.const_get(
|
177
|
-
sockaddr = ::Socket.pack_sockaddr_in(port,
|
150
|
+
def self.connect_addrinfo(addrinfo, port, timeout)
|
151
|
+
sock = new(::Socket.const_get(addrinfo[0]), Socket::SOCK_STREAM, 0)
|
152
|
+
sockaddr = ::Socket.pack_sockaddr_in(port, addrinfo[3])
|
178
153
|
|
179
154
|
begin
|
180
155
|
sock.connect_nonblock(sockaddr)
|
181
156
|
rescue Errno::EINPROGRESS
|
182
|
-
|
183
|
-
raise TimeoutError
|
184
|
-
end
|
157
|
+
raise TimeoutError unless sock.wait_writable(timeout)
|
185
158
|
|
186
159
|
begin
|
187
160
|
sock.connect_nonblock(sockaddr)
|
@@ -220,14 +193,13 @@ class Redis
|
|
220
193
|
return connect_addrinfo(ai, port, timeout)
|
221
194
|
rescue SystemCallError
|
222
195
|
# Raise if this was our last attempt.
|
223
|
-
raise if addrinfo.length == i+1
|
196
|
+
raise if addrinfo.length == i + 1
|
224
197
|
end
|
225
198
|
end
|
226
199
|
end
|
227
200
|
end
|
228
201
|
|
229
202
|
class UNIXSocket < ::Socket
|
230
|
-
|
231
203
|
include SocketMixin
|
232
204
|
|
233
205
|
def self.connect(path, timeout)
|
@@ -237,9 +209,7 @@ class Redis
|
|
237
209
|
begin
|
238
210
|
sock.connect_nonblock(sockaddr)
|
239
211
|
rescue Errno::EINPROGRESS
|
240
|
-
|
241
|
-
raise TimeoutError
|
242
|
-
end
|
212
|
+
raise TimeoutError unless sock.wait_writable(timeout)
|
243
213
|
|
244
214
|
begin
|
245
215
|
sock.connect_nonblock(sockaddr)
|
@@ -257,17 +227,58 @@ class Redis
|
|
257
227
|
class SSLSocket < ::OpenSSL::SSL::SSLSocket
|
258
228
|
include SocketMixin
|
259
229
|
|
230
|
+
unless method_defined?(:wait_readable)
|
231
|
+
def wait_readable(timeout = nil)
|
232
|
+
to_io.wait_readable(timeout)
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
unless method_defined?(:wait_writable)
|
237
|
+
def wait_writable(timeout = nil)
|
238
|
+
to_io.wait_writable(timeout)
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
260
242
|
def self.connect(host, port, timeout, ssl_params)
|
261
243
|
# Note: this is using Redis::Connection::TCPSocket
|
262
244
|
tcp_sock = TCPSocket.connect(host, port, timeout)
|
263
245
|
|
264
246
|
ctx = OpenSSL::SSL::SSLContext.new
|
265
|
-
|
247
|
+
|
248
|
+
# The provided parameters are merged into OpenSSL::SSL::SSLContext::DEFAULT_PARAMS
|
249
|
+
ctx.set_params(ssl_params || {})
|
266
250
|
|
267
251
|
ssl_sock = new(tcp_sock, ctx)
|
268
252
|
ssl_sock.hostname = host
|
269
|
-
|
270
|
-
|
253
|
+
|
254
|
+
begin
|
255
|
+
# Initiate the socket connection in the background. If it doesn't fail
|
256
|
+
# immediately it will raise an IO::WaitWritable (Errno::EINPROGRESS)
|
257
|
+
# indicating the connection is in progress.
|
258
|
+
# Unlike waiting for a tcp socket to connect, you can't time out ssl socket
|
259
|
+
# connections during the connect phase properly, because IO.select only partially works.
|
260
|
+
# Instead, you have to retry.
|
261
|
+
ssl_sock.connect_nonblock
|
262
|
+
rescue Errno::EAGAIN, Errno::EWOULDBLOCK, IO::WaitReadable
|
263
|
+
if ssl_sock.wait_readable(timeout)
|
264
|
+
retry
|
265
|
+
else
|
266
|
+
raise TimeoutError
|
267
|
+
end
|
268
|
+
rescue IO::WaitWritable
|
269
|
+
if ssl_sock.wait_writable(timeout)
|
270
|
+
retry
|
271
|
+
else
|
272
|
+
raise TimeoutError
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
unless ctx.verify_mode == OpenSSL::SSL::VERIFY_NONE || (
|
277
|
+
ctx.respond_to?(:verify_hostname) &&
|
278
|
+
!ctx.verify_hostname
|
279
|
+
)
|
280
|
+
ssl_sock.post_connection_check(host)
|
281
|
+
end
|
271
282
|
|
272
283
|
ssl_sock
|
273
284
|
end
|
@@ -277,15 +288,16 @@ class Redis
|
|
277
288
|
class Ruby
|
278
289
|
include Redis::Connection::CommandHelper
|
279
290
|
|
280
|
-
MINUS = "-"
|
281
|
-
PLUS = "+"
|
282
|
-
COLON = ":"
|
283
|
-
DOLLAR = "$"
|
284
|
-
ASTERISK = "*"
|
291
|
+
MINUS = "-"
|
292
|
+
PLUS = "+"
|
293
|
+
COLON = ":"
|
294
|
+
DOLLAR = "$"
|
295
|
+
ASTERISK = "*"
|
285
296
|
|
286
297
|
def self.connect(config)
|
287
298
|
if config[:scheme] == "unix"
|
288
299
|
raise ArgumentError, "SSL incompatible with unix sockets" if config[:ssl]
|
300
|
+
|
289
301
|
sock = UNIXSocket.connect(config[:path], config[:connect_timeout])
|
290
302
|
elsif config[:scheme] == "rediss" || config[:ssl]
|
291
303
|
sock = SSLSocket.connect(config[:host], config[:port], config[:connect_timeout], config[:ssl_params])
|
@@ -294,13 +306,14 @@ class Redis
|
|
294
306
|
end
|
295
307
|
|
296
308
|
instance = new(sock)
|
297
|
-
instance.timeout = config[:
|
309
|
+
instance.timeout = config[:read_timeout]
|
298
310
|
instance.write_timeout = config[:write_timeout]
|
299
311
|
instance.set_tcp_keepalive config[:tcp_keepalive]
|
312
|
+
instance.set_tcp_nodelay if sock.is_a? TCPSocket
|
300
313
|
instance
|
301
314
|
end
|
302
315
|
|
303
|
-
if [
|
316
|
+
if %i[SOL_SOCKET SO_KEEPALIVE SOL_TCP TCP_KEEPIDLE TCP_KEEPINTVL TCP_KEEPCNT].all? { |c| Socket.const_defined? c }
|
304
317
|
def set_tcp_keepalive(keepalive)
|
305
318
|
return unless keepalive.is_a?(Hash)
|
306
319
|
|
@@ -312,14 +325,13 @@ class Redis
|
|
312
325
|
|
313
326
|
def get_tcp_keepalive
|
314
327
|
{
|
315
|
-
:
|
316
|
-
:
|
317
|
-
:
|
328
|
+
time: @sock.getsockopt(Socket::SOL_TCP, Socket::TCP_KEEPIDLE).int,
|
329
|
+
intvl: @sock.getsockopt(Socket::SOL_TCP, Socket::TCP_KEEPINTVL).int,
|
330
|
+
probes: @sock.getsockopt(Socket::SOL_TCP, Socket::TCP_KEEPCNT).int
|
318
331
|
}
|
319
332
|
end
|
320
333
|
else
|
321
|
-
def set_tcp_keepalive(keepalive)
|
322
|
-
end
|
334
|
+
def set_tcp_keepalive(keepalive); end
|
323
335
|
|
324
336
|
def get_tcp_keepalive
|
325
337
|
{
|
@@ -327,12 +339,21 @@ class Redis
|
|
327
339
|
end
|
328
340
|
end
|
329
341
|
|
342
|
+
# disables Nagle's Algorithm, prevents multiple round trips with MULTI
|
343
|
+
if %i[IPPROTO_TCP TCP_NODELAY].all? { |c| Socket.const_defined? c }
|
344
|
+
def set_tcp_nodelay
|
345
|
+
@sock.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
|
346
|
+
end
|
347
|
+
else
|
348
|
+
def set_tcp_nodelay; end
|
349
|
+
end
|
350
|
+
|
330
351
|
def initialize(sock)
|
331
352
|
@sock = sock
|
332
353
|
end
|
333
354
|
|
334
355
|
def connected?
|
335
|
-
|
356
|
+
!!@sock
|
336
357
|
end
|
337
358
|
|
338
359
|
def disconnect
|
@@ -343,9 +364,7 @@ class Redis
|
|
343
364
|
end
|
344
365
|
|
345
366
|
def timeout=(timeout)
|
346
|
-
if @sock.respond_to?(:timeout=)
|
347
|
-
@sock.timeout = timeout
|
348
|
-
end
|
367
|
+
@sock.timeout = timeout if @sock.respond_to?(:timeout=)
|
349
368
|
end
|
350
369
|
|
351
370
|
def write_timeout=(timeout)
|
@@ -360,7 +379,6 @@ class Redis
|
|
360
379
|
line = @sock.gets
|
361
380
|
reply_type = line.slice!(0, 1)
|
362
381
|
format_reply(reply_type, line)
|
363
|
-
|
364
382
|
rescue Errno::EAGAIN
|
365
383
|
raise TimeoutError
|
366
384
|
end
|
@@ -372,7 +390,7 @@ class Redis
|
|
372
390
|
when COLON then format_integer_reply(line)
|
373
391
|
when DOLLAR then format_bulk_reply(line)
|
374
392
|
when ASTERISK then format_multi_bulk_reply(line)
|
375
|
-
else raise ProtocolError
|
393
|
+
else raise ProtocolError, reply_type
|
376
394
|
end
|
377
395
|
end
|
378
396
|
|
@@ -391,6 +409,7 @@ class Redis
|
|
391
409
|
def format_bulk_reply(line)
|
392
410
|
bulklen = line.to_i
|
393
411
|
return if bulklen == -1
|
412
|
+
|
394
413
|
reply = encode(@sock.read(bulklen))
|
395
414
|
@sock.read(2) # Discard CRLF.
|
396
415
|
reply
|
@@ -1,9 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative "command_helper"
|
2
4
|
require_relative "registry"
|
3
5
|
require_relative "../errors"
|
4
6
|
require "em-synchrony"
|
5
7
|
require "hiredis/reader"
|
6
8
|
|
9
|
+
Kernel.warn(
|
10
|
+
"The redis synchrony driver is deprecated and will be removed in redis-rb 5.0. " \
|
11
|
+
"We're looking for people to maintain it as a separate gem, see https://github.com/redis/redis-rb/issues/915"
|
12
|
+
)
|
13
|
+
|
7
14
|
class Redis
|
8
15
|
module Connection
|
9
16
|
class RedisClient < EventMachine::Connection
|
@@ -46,9 +53,7 @@ class Redis
|
|
46
53
|
|
47
54
|
def read
|
48
55
|
@req = EventMachine::DefaultDeferrable.new
|
49
|
-
if @timeout > 0
|
50
|
-
@req.timeout(@timeout, :timeout)
|
51
|
-
end
|
56
|
+
@req.timeout(@timeout, :timeout) if @timeout > 0
|
52
57
|
EventMachine::Synchrony.sync @req
|
53
58
|
end
|
54
59
|
|
@@ -72,7 +77,15 @@ class Redis
|
|
72
77
|
|
73
78
|
def self.connect(config)
|
74
79
|
if config[:scheme] == "unix"
|
75
|
-
|
80
|
+
begin
|
81
|
+
conn = EventMachine.connect_unix_domain(config[:path], RedisClient)
|
82
|
+
rescue RuntimeError => e
|
83
|
+
if e.message == "no connection"
|
84
|
+
raise Errno::ECONNREFUSED
|
85
|
+
else
|
86
|
+
raise e
|
87
|
+
end
|
88
|
+
end
|
76
89
|
elsif config[:scheme] == "rediss" || config[:ssl]
|
77
90
|
raise NotImplementedError, "SSL not supported by synchrony driver"
|
78
91
|
else
|
@@ -97,7 +110,7 @@ class Redis
|
|
97
110
|
end
|
98
111
|
|
99
112
|
def connected?
|
100
|
-
@connection
|
113
|
+
@connection&.connected?
|
101
114
|
end
|
102
115
|
|
103
116
|
def timeout=(timeout)
|