redis 4.1.4 → 4.2.4

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.
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require_relative "connection/registry"
3
4
 
4
5
  # If a connection driver was required before this file, the array
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  class Redis
3
4
  module Connection
4
5
  module CommandHelper
5
-
6
6
  COMMAND_DELIMITER = "\r\n"
7
7
 
8
8
  def build_command(args)
@@ -29,7 +29,7 @@ class Redis
29
29
  command.join(COMMAND_DELIMITER)
30
30
  end
31
31
 
32
- protected
32
+ protected
33
33
 
34
34
  def encode(string)
35
35
  string.force_encoding(Encoding.default_external)
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require_relative "registry"
3
4
  require_relative "../errors"
4
5
  require "hiredis/connection"
@@ -7,7 +8,6 @@ require "timeout"
7
8
  class Redis
8
9
  module Connection
9
10
  class Hiredis
10
-
11
11
  def self.connect(config)
12
12
  connection = ::Hiredis::Connection.new
13
13
  connect_timeout = (config.fetch(:connect_timeout, 0) * 1_000_000).to_i
@@ -32,7 +32,7 @@ class Redis
32
32
  end
33
33
 
34
34
  def connected?
35
- @connection && @connection.connected?
35
+ @connection&.connected?
36
36
  end
37
37
 
38
38
  def timeout=(timeout)
@@ -58,7 +58,7 @@ class Redis
58
58
  rescue Errno::EAGAIN
59
59
  raise TimeoutError
60
60
  rescue RuntimeError => err
61
- raise ProtocolError.new(err.message)
61
+ raise ProtocolError, err.message
62
62
  end
63
63
  end
64
64
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  class Redis
3
4
  module Connection
4
-
5
5
  # Store a list of loaded connection drivers in the Connection module.
6
6
  # Redis::Client uses the last required driver by default, and will be aware
7
7
  # of the loaded connection drivers if the user chooses to override the
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require_relative "registry"
3
4
  require_relative "command_helper"
4
5
  require_relative "../errors"
@@ -14,8 +15,7 @@ end
14
15
  class Redis
15
16
  module Connection
16
17
  module SocketMixin
17
-
18
- CRLF = "\r\n".freeze
18
+ CRLF = "\r\n"
19
19
 
20
20
  def initialize(*args)
21
21
  super(*args)
@@ -25,89 +25,77 @@ class Redis
25
25
  end
26
26
 
27
27
  def timeout=(timeout)
28
- if timeout && timeout > 0
29
- @timeout = timeout
30
- else
31
- @timeout = nil
32
- end
28
+ @timeout = (timeout if timeout && timeout > 0)
33
29
  end
34
30
 
35
31
  def write_timeout=(timeout)
36
- if timeout && timeout > 0
37
- @write_timeout = timeout
38
- else
39
- @write_timeout = nil
40
- end
32
+ @write_timeout = (timeout if timeout && timeout > 0)
41
33
  end
42
34
 
43
35
  def read(nbytes)
44
36
  result = @buffer.slice!(0, nbytes)
45
37
 
46
- while result.bytesize < nbytes
47
- result << _read_from_socket(nbytes - result.bytesize)
48
- end
38
+ result << _read_from_socket(nbytes - result.bytesize) while result.bytesize < nbytes
49
39
 
50
40
  result
51
41
  end
52
42
 
53
43
  def gets
54
- crlf = nil
55
-
56
- while (crlf = @buffer.index(CRLF)) == nil
57
- @buffer << _read_from_socket(16384)
44
+ while (crlf = @buffer.index(CRLF)).nil?
45
+ @buffer << _read_from_socket(16_384)
58
46
  end
59
47
 
60
48
  @buffer.slice!(0, crlf + CRLF.bytesize)
61
49
  end
62
50
 
63
51
  def _read_from_socket(nbytes)
64
-
65
- begin
66
- read_nonblock(nbytes)
67
-
68
- rescue IO::WaitReadable
69
- if IO.select([self], nil, nil, @timeout)
70
- retry
71
- else
72
- raise Redis::TimeoutError
73
- end
74
- rescue IO::WaitWritable
75
- if IO.select(nil, [self], nil, @timeout)
76
- retry
77
- else
78
- raise Redis::TimeoutError
52
+ loop do
53
+ case chunk = read_nonblock(nbytes, exception: false)
54
+ when :wait_readable
55
+ unless wait_readable(@timeout)
56
+ raise Redis::TimeoutError
57
+ end
58
+ when :wait_writable
59
+ unless wait_writable(@timeout)
60
+ raise Redis::TimeoutError
61
+ end
62
+ when nil
63
+ raise Errno::ECONNRESET
64
+ when String
65
+ return chunk
79
66
  end
80
67
  end
81
-
82
- rescue EOFError
83
- raise Errno::ECONNRESET
84
68
  end
85
69
 
86
70
  def _write_to_socket(data)
87
- begin
88
- write_nonblock(data)
89
-
90
- rescue IO::WaitWritable
91
- if IO.select(nil, [self], nil, @write_timeout)
92
- retry
93
- else
94
- raise Redis::TimeoutError
95
- end
96
- rescue IO::WaitReadable
97
- if IO.select([self], nil, nil, @write_timeout)
98
- retry
99
- else
100
- raise Redis::TimeoutError
71
+ total_bytes_written = 0
72
+ loop do
73
+ case bytes_written = write_nonblock(data, exception: false)
74
+ when :wait_readable
75
+ unless wait_readable(@write_timeout)
76
+ raise Redis::TimeoutError
77
+ end
78
+ when :wait_writable
79
+ unless wait_writable(@write_timeout)
80
+ raise Redis::TimeoutError
81
+ end
82
+ when nil
83
+ raise Errno::ECONNRESET
84
+ when Integer
85
+ total_bytes_written += bytes_written
86
+ if bytes_written < data.bytesize
87
+ data.slice!(0, bytes_written)
88
+ else
89
+ return total_bytes_written
90
+ end
101
91
  end
102
92
  end
103
-
104
- rescue EOFError
105
- raise Errno::ECONNRESET
106
93
  end
107
94
 
108
95
  def write(data)
109
96
  return super(data) unless @write_timeout
110
97
 
98
+ data = data.b
111
99
  length = data.bytesize
112
100
  total_count = 0
113
101
  loop do
@@ -115,6 +103,7 @@ class Redis
115
103
 
116
104
  total_count += count
117
105
  return total_count if total_count >= length
106
+
118
107
  data = data.byteslice(count..-1)
119
108
  end
120
109
  end
@@ -125,7 +114,6 @@ class Redis
125
114
  require "timeout"
126
115
 
127
116
  class TCPSocket < ::TCPSocket
128
-
129
117
  include SocketMixin
130
118
 
131
119
  def self.connect(host, port, timeout)
@@ -141,7 +129,6 @@ class Redis
141
129
  if defined?(::UNIXSocket)
142
130
 
143
131
  class UNIXSocket < ::UNIXSocket
144
-
145
132
  include SocketMixin
146
133
 
147
134
  def self.connect(path, timeout)
@@ -153,13 +140,12 @@ class Redis
153
140
  raise TimeoutError
154
141
  end
155
142
 
156
- # JRuby raises Errno::EAGAIN on #read_nonblock even when IO.select
143
+ # JRuby raises Errno::EAGAIN on #read_nonblock even when it
157
144
  # says it is readable (1.6.6, in both 1.8 and 1.9 mode).
158
145
  # Use the blocking #readpartial method instead.
159
146
 
160
147
  def _read_from_socket(nbytes)
161
148
  readpartial(nbytes)
162
-
163
149
  rescue EOFError
164
150
  raise Errno::ECONNRESET
165
151
  end
@@ -170,19 +156,16 @@ class Redis
170
156
  else
171
157
 
172
158
  class TCPSocket < ::Socket
173
-
174
159
  include SocketMixin
175
160
 
176
- def self.connect_addrinfo(ai, port, timeout)
177
- sock = new(::Socket.const_get(ai[0]), Socket::SOCK_STREAM, 0)
178
- sockaddr = ::Socket.pack_sockaddr_in(port, ai[3])
161
+ def self.connect_addrinfo(addrinfo, port, timeout)
162
+ sock = new(::Socket.const_get(addrinfo[0]), Socket::SOCK_STREAM, 0)
163
+ sockaddr = ::Socket.pack_sockaddr_in(port, addrinfo[3])
179
164
 
180
165
  begin
181
166
  sock.connect_nonblock(sockaddr)
182
167
  rescue Errno::EINPROGRESS
183
- if IO.select(nil, [sock], nil, timeout) == nil
184
- raise TimeoutError
185
- end
168
+ raise TimeoutError unless sock.wait_writable(timeout)
186
169
 
187
170
  begin
188
171
  sock.connect_nonblock(sockaddr)
@@ -221,14 +204,13 @@ class Redis
221
204
  return connect_addrinfo(ai, port, timeout)
222
205
  rescue SystemCallError
223
206
  # Raise if this was our last attempt.
224
- raise if addrinfo.length == i+1
207
+ raise if addrinfo.length == i + 1
225
208
  end
226
209
  end
227
210
  end
228
211
  end
229
212
 
230
213
  class UNIXSocket < ::Socket
231
-
232
214
  include SocketMixin
233
215
 
234
216
  def self.connect(path, timeout)
@@ -238,9 +220,7 @@ class Redis
238
220
  begin
239
221
  sock.connect_nonblock(sockaddr)
240
222
  rescue Errno::EINPROGRESS
241
- if IO.select(nil, [sock], nil, timeout) == nil
242
- raise TimeoutError
243
- end
223
+ raise TimeoutError unless sock.wait_writable(timeout)
244
224
 
245
225
  begin
246
226
  sock.connect_nonblock(sockaddr)
@@ -258,12 +238,26 @@ class Redis
258
238
  class SSLSocket < ::OpenSSL::SSL::SSLSocket
259
239
  include SocketMixin
260
240
 
241
+ unless method_defined?(:wait_readable)
242
+ def wait_readable(timeout = nil)
243
+ to_io.wait_readable(timeout)
244
+ end
245
+ end
246
+
247
+ unless method_defined?(:wait_writable)
248
+ def wait_writable(timeout = nil)
249
+ to_io.wait_writable(timeout)
250
+ end
251
+ end
252
+
261
253
  def self.connect(host, port, timeout, ssl_params)
262
254
  # Note: this is using Redis::Connection::TCPSocket
263
255
  tcp_sock = TCPSocket.connect(host, port, timeout)
264
256
 
265
257
  ctx = OpenSSL::SSL::SSLContext.new
266
- ctx.set_params(ssl_params) if ssl_params && !ssl_params.empty?
258
+
259
+ # The provided parameters are merged into OpenSSL::SSL::SSLContext::DEFAULT_PARAMS
260
+ ctx.set_params(ssl_params || {})
267
261
 
268
262
  ssl_sock = new(tcp_sock, ctx)
269
263
  ssl_sock.hostname = host
@@ -277,20 +271,23 @@ class Redis
277
271
  # Instead, you have to retry.
278
272
  ssl_sock.connect_nonblock
279
273
  rescue Errno::EAGAIN, Errno::EWOULDBLOCK, IO::WaitReadable
280
- if IO.select([ssl_sock], nil, nil, timeout)
274
+ if ssl_sock.wait_readable(timeout)
281
275
  retry
282
276
  else
283
277
  raise TimeoutError
284
278
  end
285
279
  rescue IO::WaitWritable
286
- if IO.select(nil, [ssl_sock], nil, timeout)
280
+ if ssl_sock.wait_writable(timeout)
287
281
  retry
288
282
  else
289
283
  raise TimeoutError
290
284
  end
291
285
  end
292
286
 
293
- unless ctx.verify_mode == OpenSSL::SSL::VERIFY_NONE || (ctx.respond_to?(:verify_hostname) && !ctx.verify_hostname)
287
+ unless ctx.verify_mode == OpenSSL::SSL::VERIFY_NONE || (
288
+ ctx.respond_to?(:verify_hostname) &&
289
+ !ctx.verify_hostname
290
+ )
294
291
  ssl_sock.post_connection_check(host)
295
292
  end
296
293
 
@@ -302,15 +299,16 @@ class Redis
302
299
  class Ruby
303
300
  include Redis::Connection::CommandHelper
304
301
 
305
- MINUS = "-".freeze
306
- PLUS = "+".freeze
307
- COLON = ":".freeze
308
- DOLLAR = "$".freeze
309
- ASTERISK = "*".freeze
302
+ MINUS = "-"
303
+ PLUS = "+"
304
+ COLON = ":"
305
+ DOLLAR = "$"
306
+ ASTERISK = "*"
310
307
 
311
308
  def self.connect(config)
312
309
  if config[:scheme] == "unix"
313
310
  raise ArgumentError, "SSL incompatible with unix sockets" if config[:ssl]
311
+
314
312
  sock = UNIXSocket.connect(config[:path], config[:connect_timeout])
315
313
  elsif config[:scheme] == "rediss" || config[:ssl]
316
314
  sock = SSLSocket.connect(config[:host], config[:port], config[:connect_timeout], config[:ssl_params])
@@ -326,7 +324,7 @@ class Redis
326
324
  instance
327
325
  end
328
326
 
329
- if [:SOL_SOCKET, :SO_KEEPALIVE, :SOL_TCP, :TCP_KEEPIDLE, :TCP_KEEPINTVL, :TCP_KEEPCNT].all?{|c| Socket.const_defined? c}
327
+ if %i[SOL_SOCKET SO_KEEPALIVE SOL_TCP TCP_KEEPIDLE TCP_KEEPINTVL TCP_KEEPCNT].all? { |c| Socket.const_defined? c }
330
328
  def set_tcp_keepalive(keepalive)
331
329
  return unless keepalive.is_a?(Hash)
332
330
 
@@ -338,14 +336,13 @@ class Redis
338
336
 
339
337
  def get_tcp_keepalive
340
338
  {
341
- :time => @sock.getsockopt(Socket::SOL_TCP, Socket::TCP_KEEPIDLE).int,
342
- :intvl => @sock.getsockopt(Socket::SOL_TCP, Socket::TCP_KEEPINTVL).int,
343
- :probes => @sock.getsockopt(Socket::SOL_TCP, Socket::TCP_KEEPCNT).int,
339
+ time: @sock.getsockopt(Socket::SOL_TCP, Socket::TCP_KEEPIDLE).int,
340
+ intvl: @sock.getsockopt(Socket::SOL_TCP, Socket::TCP_KEEPINTVL).int,
341
+ probes: @sock.getsockopt(Socket::SOL_TCP, Socket::TCP_KEEPCNT).int
344
342
  }
345
343
  end
346
344
  else
347
- def set_tcp_keepalive(keepalive)
348
- end
345
+ def set_tcp_keepalive(keepalive); end
349
346
 
350
347
  def get_tcp_keepalive
351
348
  {
@@ -354,13 +351,12 @@ class Redis
354
351
  end
355
352
 
356
353
  # disables Nagle's Algorithm, prevents multiple round trips with MULTI
357
- if [:IPPROTO_TCP, :TCP_NODELAY].all?{|c| Socket.const_defined? c}
354
+ if %i[IPPROTO_TCP TCP_NODELAY].all? { |c| Socket.const_defined? c }
358
355
  def set_tcp_nodelay
359
356
  @sock.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
360
357
  end
361
358
  else
362
- def set_tcp_nodelay
363
- end
359
+ def set_tcp_nodelay; end
364
360
  end
365
361
 
366
362
  def initialize(sock)
@@ -368,7 +364,7 @@ class Redis
368
364
  end
369
365
 
370
366
  def connected?
371
- !! @sock
367
+ !!@sock
372
368
  end
373
369
 
374
370
  def disconnect
@@ -379,9 +375,7 @@ class Redis
379
375
  end
380
376
 
381
377
  def timeout=(timeout)
382
- if @sock.respond_to?(:timeout=)
383
- @sock.timeout = timeout
384
- end
378
+ @sock.timeout = timeout if @sock.respond_to?(:timeout=)
385
379
  end
386
380
 
387
381
  def write_timeout=(timeout)
@@ -396,7 +390,6 @@ class Redis
396
390
  line = @sock.gets
397
391
  reply_type = line.slice!(0, 1)
398
392
  format_reply(reply_type, line)
399
-
400
393
  rescue Errno::EAGAIN
401
394
  raise TimeoutError
402
395
  end
@@ -408,7 +401,7 @@ class Redis
408
401
  when COLON then format_integer_reply(line)
409
402
  when DOLLAR then format_bulk_reply(line)
410
403
  when ASTERISK then format_multi_bulk_reply(line)
411
- else raise ProtocolError.new(reply_type)
404
+ else raise ProtocolError, reply_type
412
405
  end
413
406
  end
414
407
 
@@ -427,6 +420,7 @@ class Redis
427
420
  def format_bulk_reply(line)
428
421
  bulklen = line.to_i
429
422
  return if bulklen == -1
423
+
430
424
  reply = encode(@sock.read(bulklen))
431
425
  @sock.read(2) # Discard CRLF.
432
426
  reply