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.
Files changed (148) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +220 -0
  3. data/README.md +152 -28
  4. data/lib/redis/client.rb +171 -107
  5. data/lib/redis/cluster/command.rb +79 -0
  6. data/lib/redis/cluster/command_loader.rb +33 -0
  7. data/lib/redis/cluster/key_slot_converter.rb +72 -0
  8. data/lib/redis/cluster/node.rb +120 -0
  9. data/lib/redis/cluster/node_key.rb +31 -0
  10. data/lib/redis/cluster/node_loader.rb +34 -0
  11. data/lib/redis/cluster/option.rb +100 -0
  12. data/lib/redis/cluster/slot.rb +86 -0
  13. data/lib/redis/cluster/slot_loader.rb +46 -0
  14. data/lib/redis/cluster.rb +315 -0
  15. data/lib/redis/commands/bitmaps.rb +63 -0
  16. data/lib/redis/commands/cluster.rb +45 -0
  17. data/lib/redis/commands/connection.rb +58 -0
  18. data/lib/redis/commands/geo.rb +84 -0
  19. data/lib/redis/commands/hashes.rb +251 -0
  20. data/lib/redis/commands/hyper_log_log.rb +37 -0
  21. data/lib/redis/commands/keys.rb +455 -0
  22. data/lib/redis/commands/lists.rb +290 -0
  23. data/lib/redis/commands/pubsub.rb +72 -0
  24. data/lib/redis/commands/scripting.rb +114 -0
  25. data/lib/redis/commands/server.rb +188 -0
  26. data/lib/redis/commands/sets.rb +223 -0
  27. data/lib/redis/commands/sorted_sets.rb +812 -0
  28. data/lib/redis/commands/streams.rb +382 -0
  29. data/lib/redis/commands/strings.rb +313 -0
  30. data/lib/redis/commands/transactions.rb +139 -0
  31. data/lib/redis/commands.rb +240 -0
  32. data/lib/redis/connection/command_helper.rb +5 -2
  33. data/lib/redis/connection/hiredis.rb +7 -5
  34. data/lib/redis/connection/registry.rb +2 -1
  35. data/lib/redis/connection/ruby.rb +139 -111
  36. data/lib/redis/connection/synchrony.rb +17 -10
  37. data/lib/redis/connection.rb +3 -1
  38. data/lib/redis/distributed.rb +244 -87
  39. data/lib/redis/errors.rb +57 -0
  40. data/lib/redis/hash_ring.rb +15 -14
  41. data/lib/redis/pipeline.rb +181 -10
  42. data/lib/redis/subscribe.rb +11 -12
  43. data/lib/redis/version.rb +3 -1
  44. data/lib/redis.rb +180 -2716
  45. metadata +45 -195
  46. data/.gitignore +0 -16
  47. data/.travis/Gemfile +0 -13
  48. data/.travis.yml +0 -73
  49. data/.yardopts +0 -3
  50. data/Gemfile +0 -3
  51. data/benchmarking/logging.rb +0 -71
  52. data/benchmarking/pipeline.rb +0 -51
  53. data/benchmarking/speed.rb +0 -21
  54. data/benchmarking/suite.rb +0 -24
  55. data/benchmarking/worker.rb +0 -71
  56. data/bors.toml +0 -14
  57. data/examples/basic.rb +0 -15
  58. data/examples/consistency.rb +0 -114
  59. data/examples/dist_redis.rb +0 -43
  60. data/examples/incr-decr.rb +0 -17
  61. data/examples/list.rb +0 -26
  62. data/examples/pubsub.rb +0 -37
  63. data/examples/sentinel/sentinel.conf +0 -9
  64. data/examples/sentinel/start +0 -49
  65. data/examples/sentinel.rb +0 -41
  66. data/examples/sets.rb +0 -36
  67. data/examples/unicorn/config.ru +0 -3
  68. data/examples/unicorn/unicorn.rb +0 -20
  69. data/makefile +0 -42
  70. data/redis.gemspec +0 -42
  71. data/test/bitpos_test.rb +0 -63
  72. data/test/blocking_commands_test.rb +0 -40
  73. data/test/client_test.rb +0 -59
  74. data/test/command_map_test.rb +0 -28
  75. data/test/commands_on_hashes_test.rb +0 -19
  76. data/test/commands_on_hyper_log_log_test.rb +0 -19
  77. data/test/commands_on_lists_test.rb +0 -18
  78. data/test/commands_on_sets_test.rb +0 -75
  79. data/test/commands_on_sorted_sets_test.rb +0 -150
  80. data/test/commands_on_strings_test.rb +0 -99
  81. data/test/commands_on_value_types_test.rb +0 -171
  82. data/test/connection_handling_test.rb +0 -275
  83. data/test/connection_test.rb +0 -57
  84. data/test/db/.gitkeep +0 -0
  85. data/test/distributed_blocking_commands_test.rb +0 -44
  86. data/test/distributed_commands_on_hashes_test.rb +0 -8
  87. data/test/distributed_commands_on_hyper_log_log_test.rb +0 -31
  88. data/test/distributed_commands_on_lists_test.rb +0 -20
  89. data/test/distributed_commands_on_sets_test.rb +0 -106
  90. data/test/distributed_commands_on_sorted_sets_test.rb +0 -16
  91. data/test/distributed_commands_on_strings_test.rb +0 -69
  92. data/test/distributed_commands_on_value_types_test.rb +0 -93
  93. data/test/distributed_commands_requiring_clustering_test.rb +0 -162
  94. data/test/distributed_connection_handling_test.rb +0 -21
  95. data/test/distributed_internals_test.rb +0 -68
  96. data/test/distributed_key_tags_test.rb +0 -50
  97. data/test/distributed_persistence_control_commands_test.rb +0 -24
  98. data/test/distributed_publish_subscribe_test.rb +0 -90
  99. data/test/distributed_remote_server_control_commands_test.rb +0 -64
  100. data/test/distributed_scripting_test.rb +0 -100
  101. data/test/distributed_sorting_test.rb +0 -18
  102. data/test/distributed_test.rb +0 -56
  103. data/test/distributed_transactions_test.rb +0 -30
  104. data/test/encoding_test.rb +0 -14
  105. data/test/error_replies_test.rb +0 -57
  106. data/test/fork_safety_test.rb +0 -60
  107. data/test/helper.rb +0 -201
  108. data/test/helper_test.rb +0 -22
  109. data/test/internals_test.rb +0 -389
  110. data/test/lint/blocking_commands.rb +0 -150
  111. data/test/lint/hashes.rb +0 -162
  112. data/test/lint/hyper_log_log.rb +0 -60
  113. data/test/lint/lists.rb +0 -143
  114. data/test/lint/sets.rb +0 -140
  115. data/test/lint/sorted_sets.rb +0 -316
  116. data/test/lint/strings.rb +0 -246
  117. data/test/lint/value_types.rb +0 -130
  118. data/test/persistence_control_commands_test.rb +0 -24
  119. data/test/pipelining_commands_test.rb +0 -238
  120. data/test/publish_subscribe_test.rb +0 -280
  121. data/test/remote_server_control_commands_test.rb +0 -175
  122. data/test/scanning_test.rb +0 -407
  123. data/test/scripting_test.rb +0 -76
  124. data/test/sentinel_command_test.rb +0 -78
  125. data/test/sentinel_test.rb +0 -253
  126. data/test/sorting_test.rb +0 -57
  127. data/test/ssl_test.rb +0 -69
  128. data/test/support/connection/hiredis.rb +0 -1
  129. data/test/support/connection/ruby.rb +0 -1
  130. data/test/support/connection/synchrony.rb +0 -17
  131. data/test/support/redis_mock.rb +0 -130
  132. data/test/support/ssl/gen_certs.sh +0 -31
  133. data/test/support/ssl/trusted-ca.crt +0 -25
  134. data/test/support/ssl/trusted-ca.key +0 -27
  135. data/test/support/ssl/trusted-cert.crt +0 -81
  136. data/test/support/ssl/trusted-cert.key +0 -28
  137. data/test/support/ssl/untrusted-ca.crt +0 -26
  138. data/test/support/ssl/untrusted-ca.key +0 -27
  139. data/test/support/ssl/untrusted-cert.crt +0 -82
  140. data/test/support/ssl/untrusted-cert.key +0 -28
  141. data/test/support/wire/synchrony.rb +0 -24
  142. data/test/support/wire/thread.rb +0 -5
  143. data/test/synchrony_driver.rb +0 -85
  144. data/test/test.conf.erb +0 -9
  145. data/test/thread_safety_test.rb +0 -60
  146. data/test/transactions_test.rb +0 -262
  147. data/test/unknown_commands_test.rb +0 -12
  148. data/test/url_param_test.rb +0 -136
@@ -1,6 +1,9 @@
1
- require_relative "registry"
2
- require_relative "command_helper"
3
- require_relative "../errors"
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 = "".dup
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
- while result.bytesize < nbytes
46
- result << _read_from_socket(nbytes - result.bytesize)
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
- begin
65
- read_nonblock(nbytes)
66
-
67
- rescue IO::WaitReadable
68
- if IO.select([self], nil, nil, @timeout)
69
- retry
70
- else
71
- raise Redis::TimeoutError
72
- end
73
- rescue IO::WaitWritable
74
- if IO.select(nil, [self], nil, @timeout)
75
- retry
76
- else
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(data)
108
- return super(data) unless @write_timeout
72
+ def write(buffer)
73
+ return super(buffer) unless @write_timeout
109
74
 
110
- length = data.bytesize
111
- total_count = 0
75
+ bytes_to_write = buffer.bytesize
76
+ total_bytes_written = 0
112
77
  loop do
113
- count = _write_to_socket(data)
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
- total_count += count
116
- return total_count if total_count >= length
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 IO.select
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(ai, port, timeout)
176
- sock = new(::Socket.const_get(ai[0]), Socket::SOCK_STREAM, 0)
177
- sockaddr = ::Socket.pack_sockaddr_in(port, ai[3])
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
- if IO.select(nil, [sock], nil, timeout) == nil
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
- if IO.select(nil, [sock], nil, timeout) == nil
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
- # Note: this is using Redis::Connection::TCPSocket
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
- ctx.set_params(ssl_params) if ssl_params && !ssl_params.empty?
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
- ssl_sock.connect
270
- ssl_sock.post_connection_check(host)
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 = "-".freeze
281
- PLUS = "+".freeze
282
- COLON = ":".freeze
283
- DOLLAR = "$".freeze
284
- ASTERISK = "*".freeze
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[:timeout]
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 [:SOL_SOCKET, :SO_KEEPALIVE, :SOL_TCP, :TCP_KEEPIDLE, :TCP_KEEPINTVL, :TCP_KEEPCNT].all?{|c| Socket.const_defined? c}
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
- :time => @sock.getsockopt(Socket::SOL_TCP, Socket::TCP_KEEPIDLE).int,
316
- :intvl => @sock.getsockopt(Socket::SOL_TCP, Socket::TCP_KEEPINTVL).int,
317
- :probes => @sock.getsockopt(Socket::SOL_TCP, Socket::TCP_KEEPCNT).int,
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
- !! @sock
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.new(reply_type)
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
- require_relative "command_helper"
2
- require_relative "registry"
3
- require_relative "../errors"
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 && @connection.connected?
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
- if type == :reply
133
+ case type
134
+ when :reply
128
135
  payload
129
- elsif type == :error
136
+ when :error
130
137
  raise payload
131
- elsif type == :timeout
138
+ when :timeout
132
139
  raise TimeoutError
133
140
  else
134
141
  raise "Unknown type #{type.inspect}"
@@ -1,4 +1,6 @@
1
- require_relative "connection/registry"
1
+ # frozen_string_literal: true
2
+
3
+ require "redis/connection/registry"
2
4
 
3
5
  # If a connection driver was required before this file, the array
4
6
  # Redis::Connection.drivers will contain one or more classes. The last driver