redis 4.0.1 → 4.8.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 +220 -0
- data/README.md +152 -28
- data/lib/redis/client.rb +171 -107
- data/lib/redis/cluster/command.rb +79 -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 +120 -0
- data/lib/redis/cluster/node_key.rb +31 -0
- data/lib/redis/cluster/node_loader.rb +34 -0
- data/lib/redis/cluster/option.rb +100 -0
- data/lib/redis/cluster/slot.rb +86 -0
- data/lib/redis/cluster/slot_loader.rb +46 -0
- data/lib/redis/cluster.rb +315 -0
- data/lib/redis/commands/bitmaps.rb +63 -0
- data/lib/redis/commands/cluster.rb +45 -0
- data/lib/redis/commands/connection.rb +58 -0
- data/lib/redis/commands/geo.rb +84 -0
- data/lib/redis/commands/hashes.rb +251 -0
- data/lib/redis/commands/hyper_log_log.rb +37 -0
- data/lib/redis/commands/keys.rb +455 -0
- data/lib/redis/commands/lists.rb +290 -0
- data/lib/redis/commands/pubsub.rb +72 -0
- data/lib/redis/commands/scripting.rb +114 -0
- data/lib/redis/commands/server.rb +188 -0
- data/lib/redis/commands/sets.rb +223 -0
- data/lib/redis/commands/sorted_sets.rb +812 -0
- data/lib/redis/commands/streams.rb +382 -0
- data/lib/redis/commands/strings.rb +313 -0
- data/lib/redis/commands/transactions.rb +139 -0
- data/lib/redis/commands.rb +240 -0
- data/lib/redis/connection/command_helper.rb +5 -2
- data/lib/redis/connection/hiredis.rb +7 -5
- data/lib/redis/connection/registry.rb +2 -1
- data/lib/redis/connection/ruby.rb +139 -111
- data/lib/redis/connection/synchrony.rb +17 -10
- data/lib/redis/connection.rb +3 -1
- data/lib/redis/distributed.rb +244 -87
- data/lib/redis/errors.rb +57 -0
- data/lib/redis/hash_ring.rb +15 -14
- data/lib/redis/pipeline.rb +181 -10
- data/lib/redis/subscribe.rb +11 -12
- data/lib/redis/version.rb +3 -1
- data/lib/redis.rb +180 -2716
- metadata +45 -195
- data/.gitignore +0 -16
- data/.travis/Gemfile +0 -13
- data/.travis.yml +0 -73
- 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/bors.toml +0 -14
- data/examples/basic.rb +0 -15
- data/examples/consistency.rb +0 -114
- 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 -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 -42
- data/test/bitpos_test.rb +0 -63
- data/test/blocking_commands_test.rb +0 -40
- data/test/client_test.rb +0 -59
- data/test/command_map_test.rb +0 -28
- data/test/commands_on_hashes_test.rb +0 -19
- data/test/commands_on_hyper_log_log_test.rb +0 -19
- data/test/commands_on_lists_test.rb +0 -18
- data/test/commands_on_sets_test.rb +0 -75
- data/test/commands_on_sorted_sets_test.rb +0 -150
- data/test/commands_on_strings_test.rb +0 -99
- data/test/commands_on_value_types_test.rb +0 -171
- data/test/connection_handling_test.rb +0 -275
- data/test/connection_test.rb +0 -57
- data/test/db/.gitkeep +0 -0
- data/test/distributed_blocking_commands_test.rb +0 -44
- data/test/distributed_commands_on_hashes_test.rb +0 -8
- data/test/distributed_commands_on_hyper_log_log_test.rb +0 -31
- data/test/distributed_commands_on_lists_test.rb +0 -20
- data/test/distributed_commands_on_sets_test.rb +0 -106
- data/test/distributed_commands_on_sorted_sets_test.rb +0 -16
- data/test/distributed_commands_on_strings_test.rb +0 -69
- data/test/distributed_commands_on_value_types_test.rb +0 -93
- data/test/distributed_commands_requiring_clustering_test.rb +0 -162
- data/test/distributed_connection_handling_test.rb +0 -21
- data/test/distributed_internals_test.rb +0 -68
- data/test/distributed_key_tags_test.rb +0 -50
- data/test/distributed_persistence_control_commands_test.rb +0 -24
- data/test/distributed_publish_subscribe_test.rb +0 -90
- data/test/distributed_remote_server_control_commands_test.rb +0 -64
- data/test/distributed_scripting_test.rb +0 -100
- data/test/distributed_sorting_test.rb +0 -18
- data/test/distributed_test.rb +0 -56
- data/test/distributed_transactions_test.rb +0 -30
- 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 -201
- data/test/helper_test.rb +0 -22
- data/test/internals_test.rb +0 -389
- data/test/lint/blocking_commands.rb +0 -150
- data/test/lint/hashes.rb +0 -162
- data/test/lint/hyper_log_log.rb +0 -60
- data/test/lint/lists.rb +0 -143
- data/test/lint/sets.rb +0 -140
- data/test/lint/sorted_sets.rb +0 -316
- data/test/lint/strings.rb +0 -246
- data/test/lint/value_types.rb +0 -130
- 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,6 +1,9 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "redis/connection/registry"
|
4
|
+
require "redis/connection/command_helper"
|
5
|
+
require "redis/errors"
|
6
|
+
|
4
7
|
require "socket"
|
5
8
|
require "timeout"
|
6
9
|
|
@@ -13,108 +16,85 @@ end
|
|
13
16
|
class Redis
|
14
17
|
module Connection
|
15
18
|
module SocketMixin
|
16
|
-
|
17
|
-
CRLF = "\r\n".freeze
|
19
|
+
CRLF = "\r\n"
|
18
20
|
|
19
21
|
def initialize(*args)
|
20
22
|
super(*args)
|
21
23
|
|
22
24
|
@timeout = @write_timeout = nil
|
23
|
-
@buffer = "".
|
25
|
+
@buffer = "".b
|
24
26
|
end
|
25
27
|
|
26
28
|
def timeout=(timeout)
|
27
|
-
if timeout && timeout > 0
|
28
|
-
@timeout = timeout
|
29
|
-
else
|
30
|
-
@timeout = nil
|
31
|
-
end
|
29
|
+
@timeout = (timeout if timeout && timeout > 0)
|
32
30
|
end
|
33
31
|
|
34
32
|
def write_timeout=(timeout)
|
35
|
-
if timeout && timeout > 0
|
36
|
-
@write_timeout = timeout
|
37
|
-
else
|
38
|
-
@write_timeout = nil
|
39
|
-
end
|
33
|
+
@write_timeout = (timeout if timeout && timeout > 0)
|
40
34
|
end
|
41
35
|
|
42
36
|
def read(nbytes)
|
43
37
|
result = @buffer.slice!(0, nbytes)
|
44
38
|
|
45
|
-
|
46
|
-
|
47
|
-
end
|
39
|
+
buffer = String.new(capacity: nbytes, encoding: Encoding::ASCII_8BIT)
|
40
|
+
result << _read_from_socket(nbytes - result.bytesize, buffer) while result.bytesize < nbytes
|
48
41
|
|
49
42
|
result
|
50
43
|
end
|
51
44
|
|
52
45
|
def gets
|
53
|
-
crlf = nil
|
54
|
-
|
55
|
-
while (crlf = @buffer.index(CRLF)) == nil
|
56
|
-
@buffer << _read_from_socket(1024)
|
46
|
+
while (crlf = @buffer.index(CRLF)).nil?
|
47
|
+
@buffer << _read_from_socket(16_384)
|
57
48
|
end
|
58
49
|
|
59
50
|
@buffer.slice!(0, crlf + CRLF.bytesize)
|
60
51
|
end
|
61
52
|
|
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
|
53
|
+
def _read_from_socket(nbytes, buffer = nil)
|
54
|
+
loop do
|
55
|
+
case chunk = read_nonblock(nbytes, buffer, exception: false)
|
56
|
+
when :wait_readable
|
57
|
+
unless wait_readable(@timeout)
|
58
|
+
raise Redis::TimeoutError
|
59
|
+
end
|
60
|
+
when :wait_writable
|
61
|
+
unless wait_writable(@timeout)
|
62
|
+
raise Redis::TimeoutError
|
63
|
+
end
|
64
|
+
when nil
|
65
|
+
raise Errno::ECONNRESET
|
66
|
+
when String
|
67
|
+
return chunk
|
100
68
|
end
|
101
69
|
end
|
102
|
-
|
103
|
-
rescue EOFError
|
104
|
-
raise Errno::ECONNRESET
|
105
70
|
end
|
106
71
|
|
107
|
-
def write(
|
108
|
-
return super(
|
72
|
+
def write(buffer)
|
73
|
+
return super(buffer) unless @write_timeout
|
109
74
|
|
110
|
-
|
111
|
-
|
75
|
+
bytes_to_write = buffer.bytesize
|
76
|
+
total_bytes_written = 0
|
112
77
|
loop do
|
113
|
-
|
78
|
+
case bytes_written = write_nonblock(buffer, exception: false)
|
79
|
+
when :wait_readable
|
80
|
+
unless wait_readable(@write_timeout)
|
81
|
+
raise Redis::TimeoutError
|
82
|
+
end
|
83
|
+
when :wait_writable
|
84
|
+
unless wait_writable(@write_timeout)
|
85
|
+
raise Redis::TimeoutError
|
86
|
+
end
|
87
|
+
when nil
|
88
|
+
raise Errno::ECONNRESET
|
89
|
+
when Integer
|
90
|
+
total_bytes_written += bytes_written
|
91
|
+
|
92
|
+
if total_bytes_written >= bytes_to_write
|
93
|
+
return total_bytes_written
|
94
|
+
end
|
114
95
|
|
115
|
-
|
116
|
-
|
117
|
-
data = data.byteslice(count..-1)
|
96
|
+
buffer = buffer.byteslice(bytes_written..-1)
|
97
|
+
end
|
118
98
|
end
|
119
99
|
end
|
120
100
|
end
|
@@ -124,7 +104,6 @@ class Redis
|
|
124
104
|
require "timeout"
|
125
105
|
|
126
106
|
class TCPSocket < ::TCPSocket
|
127
|
-
|
128
107
|
include SocketMixin
|
129
108
|
|
130
109
|
def self.connect(host, port, timeout)
|
@@ -140,7 +119,6 @@ class Redis
|
|
140
119
|
if defined?(::UNIXSocket)
|
141
120
|
|
142
121
|
class UNIXSocket < ::UNIXSocket
|
143
|
-
|
144
122
|
include SocketMixin
|
145
123
|
|
146
124
|
def self.connect(path, timeout)
|
@@ -152,13 +130,14 @@ class Redis
|
|
152
130
|
raise TimeoutError
|
153
131
|
end
|
154
132
|
|
155
|
-
# JRuby raises Errno::EAGAIN on #read_nonblock even when
|
133
|
+
# JRuby raises Errno::EAGAIN on #read_nonblock even when it
|
156
134
|
# says it is readable (1.6.6, in both 1.8 and 1.9 mode).
|
157
135
|
# Use the blocking #readpartial method instead.
|
158
136
|
|
159
|
-
def _read_from_socket(nbytes)
|
137
|
+
def _read_from_socket(nbytes, _buffer = nil)
|
138
|
+
# JRuby: Throw away the buffer as we won't need it
|
139
|
+
# but still need to support the max arity of 2
|
160
140
|
readpartial(nbytes)
|
161
|
-
|
162
141
|
rescue EOFError
|
163
142
|
raise Errno::ECONNRESET
|
164
143
|
end
|
@@ -169,19 +148,16 @@ class Redis
|
|
169
148
|
else
|
170
149
|
|
171
150
|
class TCPSocket < ::Socket
|
172
|
-
|
173
151
|
include SocketMixin
|
174
152
|
|
175
|
-
def self.connect_addrinfo(
|
176
|
-
sock = new(::Socket.const_get(
|
177
|
-
sockaddr = ::Socket.pack_sockaddr_in(port,
|
153
|
+
def self.connect_addrinfo(addrinfo, port, timeout)
|
154
|
+
sock = new(::Socket.const_get(addrinfo[0]), Socket::SOCK_STREAM, 0)
|
155
|
+
sockaddr = ::Socket.pack_sockaddr_in(port, addrinfo[3])
|
178
156
|
|
179
157
|
begin
|
180
158
|
sock.connect_nonblock(sockaddr)
|
181
159
|
rescue Errno::EINPROGRESS
|
182
|
-
|
183
|
-
raise TimeoutError
|
184
|
-
end
|
160
|
+
raise TimeoutError unless sock.wait_writable(timeout)
|
185
161
|
|
186
162
|
begin
|
187
163
|
sock.connect_nonblock(sockaddr)
|
@@ -220,14 +196,13 @@ class Redis
|
|
220
196
|
return connect_addrinfo(ai, port, timeout)
|
221
197
|
rescue SystemCallError
|
222
198
|
# Raise if this was our last attempt.
|
223
|
-
raise if addrinfo.length == i+1
|
199
|
+
raise if addrinfo.length == i + 1
|
224
200
|
end
|
225
201
|
end
|
226
202
|
end
|
227
203
|
end
|
228
204
|
|
229
205
|
class UNIXSocket < ::Socket
|
230
|
-
|
231
206
|
include SocketMixin
|
232
207
|
|
233
208
|
def self.connect(path, timeout)
|
@@ -237,9 +212,7 @@ class Redis
|
|
237
212
|
begin
|
238
213
|
sock.connect_nonblock(sockaddr)
|
239
214
|
rescue Errno::EINPROGRESS
|
240
|
-
|
241
|
-
raise TimeoutError
|
242
|
-
end
|
215
|
+
raise TimeoutError unless sock.wait_writable(timeout)
|
243
216
|
|
244
217
|
begin
|
245
218
|
sock.connect_nonblock(sockaddr)
|
@@ -257,17 +230,58 @@ class Redis
|
|
257
230
|
class SSLSocket < ::OpenSSL::SSL::SSLSocket
|
258
231
|
include SocketMixin
|
259
232
|
|
233
|
+
unless method_defined?(:wait_readable)
|
234
|
+
def wait_readable(timeout = nil)
|
235
|
+
to_io.wait_readable(timeout)
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
unless method_defined?(:wait_writable)
|
240
|
+
def wait_writable(timeout = nil)
|
241
|
+
to_io.wait_writable(timeout)
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
260
245
|
def self.connect(host, port, timeout, ssl_params)
|
261
|
-
#
|
246
|
+
# NOTE: this is using Redis::Connection::TCPSocket
|
262
247
|
tcp_sock = TCPSocket.connect(host, port, timeout)
|
263
248
|
|
264
249
|
ctx = OpenSSL::SSL::SSLContext.new
|
265
|
-
|
250
|
+
|
251
|
+
# The provided parameters are merged into OpenSSL::SSL::SSLContext::DEFAULT_PARAMS
|
252
|
+
ctx.set_params(ssl_params || {})
|
266
253
|
|
267
254
|
ssl_sock = new(tcp_sock, ctx)
|
268
255
|
ssl_sock.hostname = host
|
269
|
-
|
270
|
-
|
256
|
+
|
257
|
+
begin
|
258
|
+
# Initiate the socket connection in the background. If it doesn't fail
|
259
|
+
# immediately it will raise an IO::WaitWritable (Errno::EINPROGRESS)
|
260
|
+
# indicating the connection is in progress.
|
261
|
+
# Unlike waiting for a tcp socket to connect, you can't time out ssl socket
|
262
|
+
# connections during the connect phase properly, because IO.select only partially works.
|
263
|
+
# Instead, you have to retry.
|
264
|
+
ssl_sock.connect_nonblock
|
265
|
+
rescue Errno::EAGAIN, Errno::EWOULDBLOCK, IO::WaitReadable
|
266
|
+
if ssl_sock.wait_readable(timeout)
|
267
|
+
retry
|
268
|
+
else
|
269
|
+
raise TimeoutError
|
270
|
+
end
|
271
|
+
rescue IO::WaitWritable
|
272
|
+
if ssl_sock.wait_writable(timeout)
|
273
|
+
retry
|
274
|
+
else
|
275
|
+
raise TimeoutError
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
unless ctx.verify_mode == OpenSSL::SSL::VERIFY_NONE || (
|
280
|
+
ctx.respond_to?(:verify_hostname) &&
|
281
|
+
!ctx.verify_hostname
|
282
|
+
)
|
283
|
+
ssl_sock.post_connection_check(host)
|
284
|
+
end
|
271
285
|
|
272
286
|
ssl_sock
|
273
287
|
end
|
@@ -277,15 +291,16 @@ class Redis
|
|
277
291
|
class Ruby
|
278
292
|
include Redis::Connection::CommandHelper
|
279
293
|
|
280
|
-
MINUS = "-"
|
281
|
-
PLUS = "+"
|
282
|
-
COLON = ":"
|
283
|
-
DOLLAR = "$"
|
284
|
-
ASTERISK = "*"
|
294
|
+
MINUS = "-"
|
295
|
+
PLUS = "+"
|
296
|
+
COLON = ":"
|
297
|
+
DOLLAR = "$"
|
298
|
+
ASTERISK = "*"
|
285
299
|
|
286
300
|
def self.connect(config)
|
287
301
|
if config[:scheme] == "unix"
|
288
302
|
raise ArgumentError, "SSL incompatible with unix sockets" if config[:ssl]
|
303
|
+
|
289
304
|
sock = UNIXSocket.connect(config[:path], config[:connect_timeout])
|
290
305
|
elsif config[:scheme] == "rediss" || config[:ssl]
|
291
306
|
sock = SSLSocket.connect(config[:host], config[:port], config[:connect_timeout], config[:ssl_params])
|
@@ -294,13 +309,14 @@ class Redis
|
|
294
309
|
end
|
295
310
|
|
296
311
|
instance = new(sock)
|
297
|
-
instance.timeout = config[:
|
312
|
+
instance.timeout = config[:read_timeout]
|
298
313
|
instance.write_timeout = config[:write_timeout]
|
299
314
|
instance.set_tcp_keepalive config[:tcp_keepalive]
|
315
|
+
instance.set_tcp_nodelay if sock.is_a? TCPSocket
|
300
316
|
instance
|
301
317
|
end
|
302
318
|
|
303
|
-
if [
|
319
|
+
if %i[SOL_SOCKET SO_KEEPALIVE SOL_TCP TCP_KEEPIDLE TCP_KEEPINTVL TCP_KEEPCNT].all? { |c| Socket.const_defined? c }
|
304
320
|
def set_tcp_keepalive(keepalive)
|
305
321
|
return unless keepalive.is_a?(Hash)
|
306
322
|
|
@@ -312,14 +328,13 @@ class Redis
|
|
312
328
|
|
313
329
|
def get_tcp_keepalive
|
314
330
|
{
|
315
|
-
:
|
316
|
-
:
|
317
|
-
:
|
331
|
+
time: @sock.getsockopt(Socket::SOL_TCP, Socket::TCP_KEEPIDLE).int,
|
332
|
+
intvl: @sock.getsockopt(Socket::SOL_TCP, Socket::TCP_KEEPINTVL).int,
|
333
|
+
probes: @sock.getsockopt(Socket::SOL_TCP, Socket::TCP_KEEPCNT).int
|
318
334
|
}
|
319
335
|
end
|
320
336
|
else
|
321
|
-
def set_tcp_keepalive(keepalive)
|
322
|
-
end
|
337
|
+
def set_tcp_keepalive(keepalive); end
|
323
338
|
|
324
339
|
def get_tcp_keepalive
|
325
340
|
{
|
@@ -327,12 +342,21 @@ class Redis
|
|
327
342
|
end
|
328
343
|
end
|
329
344
|
|
345
|
+
# disables Nagle's Algorithm, prevents multiple round trips with MULTI
|
346
|
+
if %i[IPPROTO_TCP TCP_NODELAY].all? { |c| Socket.const_defined? c }
|
347
|
+
def set_tcp_nodelay
|
348
|
+
@sock.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
|
349
|
+
end
|
350
|
+
else
|
351
|
+
def set_tcp_nodelay; end
|
352
|
+
end
|
353
|
+
|
330
354
|
def initialize(sock)
|
331
355
|
@sock = sock
|
332
356
|
end
|
333
357
|
|
334
358
|
def connected?
|
335
|
-
|
359
|
+
!!@sock
|
336
360
|
end
|
337
361
|
|
338
362
|
def disconnect
|
@@ -343,9 +367,7 @@ class Redis
|
|
343
367
|
end
|
344
368
|
|
345
369
|
def timeout=(timeout)
|
346
|
-
if @sock.respond_to?(:timeout=)
|
347
|
-
@sock.timeout = timeout
|
348
|
-
end
|
370
|
+
@sock.timeout = timeout if @sock.respond_to?(:timeout=)
|
349
371
|
end
|
350
372
|
|
351
373
|
def write_timeout=(timeout)
|
@@ -360,9 +382,14 @@ class Redis
|
|
360
382
|
line = @sock.gets
|
361
383
|
reply_type = line.slice!(0, 1)
|
362
384
|
format_reply(reply_type, line)
|
363
|
-
|
364
385
|
rescue Errno::EAGAIN
|
365
386
|
raise TimeoutError
|
387
|
+
rescue OpenSSL::SSL::SSLError => ssl_error
|
388
|
+
if ssl_error.message.match?(/SSL_read: unexpected eof while reading/i)
|
389
|
+
raise EOFError, ssl_error.message
|
390
|
+
else
|
391
|
+
raise
|
392
|
+
end
|
366
393
|
end
|
367
394
|
|
368
395
|
def format_reply(reply_type, line)
|
@@ -372,7 +399,7 @@ class Redis
|
|
372
399
|
when COLON then format_integer_reply(line)
|
373
400
|
when DOLLAR then format_bulk_reply(line)
|
374
401
|
when ASTERISK then format_multi_bulk_reply(line)
|
375
|
-
else raise ProtocolError
|
402
|
+
else raise ProtocolError, reply_type
|
376
403
|
end
|
377
404
|
end
|
378
405
|
|
@@ -391,6 +418,7 @@ class Redis
|
|
391
418
|
def format_bulk_reply(line)
|
392
419
|
bulklen = line.to_i
|
393
420
|
return if bulklen == -1
|
421
|
+
|
394
422
|
reply = encode(@sock.read(bulklen))
|
395
423
|
@sock.read(2) # Discard CRLF.
|
396
424
|
reply
|
@@ -1,9 +1,17 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "redis/connection/registry"
|
4
|
+
require "redis/connection/command_helper"
|
5
|
+
require "redis/errors"
|
6
|
+
|
4
7
|
require "em-synchrony"
|
5
8
|
require "hiredis/reader"
|
6
9
|
|
10
|
+
::Redis.deprecate!(
|
11
|
+
"The redis synchrony driver is deprecated and will be removed in redis-rb 5.0.0. " \
|
12
|
+
"We're looking for people to maintain it as a separate gem, see https://github.com/redis/redis-rb/issues/915"
|
13
|
+
)
|
14
|
+
|
7
15
|
class Redis
|
8
16
|
module Connection
|
9
17
|
class RedisClient < EventMachine::Connection
|
@@ -46,9 +54,7 @@ class Redis
|
|
46
54
|
|
47
55
|
def read
|
48
56
|
@req = EventMachine::DefaultDeferrable.new
|
49
|
-
if @timeout > 0
|
50
|
-
@req.timeout(@timeout, :timeout)
|
51
|
-
end
|
57
|
+
@req.timeout(@timeout, :timeout) if @timeout > 0
|
52
58
|
EventMachine::Synchrony.sync @req
|
53
59
|
end
|
54
60
|
|
@@ -105,7 +111,7 @@ class Redis
|
|
105
111
|
end
|
106
112
|
|
107
113
|
def connected?
|
108
|
-
@connection
|
114
|
+
@connection&.connected?
|
109
115
|
end
|
110
116
|
|
111
117
|
def timeout=(timeout)
|
@@ -124,11 +130,12 @@ class Redis
|
|
124
130
|
def read
|
125
131
|
type, payload = @connection.read
|
126
132
|
|
127
|
-
|
133
|
+
case type
|
134
|
+
when :reply
|
128
135
|
payload
|
129
|
-
|
136
|
+
when :error
|
130
137
|
raise payload
|
131
|
-
|
138
|
+
when :timeout
|
132
139
|
raise TimeoutError
|
133
140
|
else
|
134
141
|
raise "Unknown type #{type.inspect}"
|
data/lib/redis/connection.rb
CHANGED