redis 4.0.3 → 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.
Files changed (157) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +110 -0
  3. data/README.md +126 -17
  4. data/lib/redis/client.rb +130 -82
  5. data/lib/redis/cluster/command_loader.rb +8 -7
  6. data/lib/redis/cluster/node.rb +5 -1
  7. data/lib/redis/cluster/node_key.rb +3 -7
  8. data/lib/redis/cluster/node_loader.rb +2 -0
  9. data/lib/redis/cluster/option.rb +31 -14
  10. data/lib/redis/cluster/slot.rb +30 -13
  11. data/lib/redis/cluster/slot_loader.rb +6 -4
  12. data/lib/redis/cluster.rb +23 -17
  13. data/lib/redis/connection/command_helper.rb +5 -2
  14. data/lib/redis/connection/hiredis.rb +4 -3
  15. data/lib/redis/connection/registry.rb +2 -1
  16. data/lib/redis/connection/ruby.rb +139 -106
  17. data/lib/redis/connection/synchrony.rb +9 -4
  18. data/lib/redis/connection.rb +2 -0
  19. data/lib/redis/distributed.rb +171 -70
  20. data/lib/redis/errors.rb +2 -0
  21. data/lib/redis/hash_ring.rb +15 -14
  22. data/lib/redis/pipeline.rb +46 -8
  23. data/lib/redis/subscribe.rb +11 -12
  24. data/lib/redis/version.rb +3 -1
  25. data/lib/redis.rb +1239 -426
  26. metadata +16 -262
  27. data/.gitignore +0 -19
  28. data/.travis/Gemfile +0 -18
  29. data/.travis.yml +0 -61
  30. data/.yardopts +0 -3
  31. data/Gemfile +0 -8
  32. data/benchmarking/logging.rb +0 -71
  33. data/benchmarking/pipeline.rb +0 -51
  34. data/benchmarking/speed.rb +0 -21
  35. data/benchmarking/suite.rb +0 -24
  36. data/benchmarking/worker.rb +0 -71
  37. data/bin/build +0 -71
  38. data/bors.toml +0 -14
  39. data/examples/basic.rb +0 -15
  40. data/examples/consistency.rb +0 -114
  41. data/examples/dist_redis.rb +0 -43
  42. data/examples/incr-decr.rb +0 -17
  43. data/examples/list.rb +0 -26
  44. data/examples/pubsub.rb +0 -37
  45. data/examples/sentinel/sentinel.conf +0 -9
  46. data/examples/sentinel/start +0 -49
  47. data/examples/sentinel.rb +0 -41
  48. data/examples/sets.rb +0 -36
  49. data/examples/unicorn/config.ru +0 -3
  50. data/examples/unicorn/unicorn.rb +0 -20
  51. data/makefile +0 -74
  52. data/redis.gemspec +0 -43
  53. data/test/bitpos_test.rb +0 -63
  54. data/test/blocking_commands_test.rb +0 -40
  55. data/test/client_test.rb +0 -76
  56. data/test/cluster_abnormal_state_test.rb +0 -38
  57. data/test/cluster_blocking_commands_test.rb +0 -15
  58. data/test/cluster_client_internals_test.rb +0 -77
  59. data/test/cluster_client_key_hash_tags_test.rb +0 -88
  60. data/test/cluster_client_options_test.rb +0 -147
  61. data/test/cluster_client_pipelining_test.rb +0 -59
  62. data/test/cluster_client_replicas_test.rb +0 -36
  63. data/test/cluster_client_slots_test.rb +0 -94
  64. data/test/cluster_client_transactions_test.rb +0 -71
  65. data/test/cluster_commands_on_cluster_test.rb +0 -165
  66. data/test/cluster_commands_on_connection_test.rb +0 -40
  67. data/test/cluster_commands_on_geo_test.rb +0 -74
  68. data/test/cluster_commands_on_hashes_test.rb +0 -11
  69. data/test/cluster_commands_on_hyper_log_log_test.rb +0 -17
  70. data/test/cluster_commands_on_keys_test.rb +0 -134
  71. data/test/cluster_commands_on_lists_test.rb +0 -15
  72. data/test/cluster_commands_on_pub_sub_test.rb +0 -101
  73. data/test/cluster_commands_on_scripting_test.rb +0 -56
  74. data/test/cluster_commands_on_server_test.rb +0 -221
  75. data/test/cluster_commands_on_sets_test.rb +0 -39
  76. data/test/cluster_commands_on_sorted_sets_test.rb +0 -35
  77. data/test/cluster_commands_on_streams_test.rb +0 -196
  78. data/test/cluster_commands_on_strings_test.rb +0 -15
  79. data/test/cluster_commands_on_transactions_test.rb +0 -41
  80. data/test/cluster_commands_on_value_types_test.rb +0 -14
  81. data/test/command_map_test.rb +0 -28
  82. data/test/commands_on_geo_test.rb +0 -116
  83. data/test/commands_on_hashes_test.rb +0 -7
  84. data/test/commands_on_hyper_log_log_test.rb +0 -7
  85. data/test/commands_on_lists_test.rb +0 -7
  86. data/test/commands_on_sets_test.rb +0 -7
  87. data/test/commands_on_sorted_sets_test.rb +0 -7
  88. data/test/commands_on_strings_test.rb +0 -7
  89. data/test/commands_on_value_types_test.rb +0 -207
  90. data/test/connection_handling_test.rb +0 -275
  91. data/test/connection_test.rb +0 -57
  92. data/test/db/.gitkeep +0 -0
  93. data/test/distributed_blocking_commands_test.rb +0 -52
  94. data/test/distributed_commands_on_hashes_test.rb +0 -21
  95. data/test/distributed_commands_on_hyper_log_log_test.rb +0 -26
  96. data/test/distributed_commands_on_lists_test.rb +0 -19
  97. data/test/distributed_commands_on_sets_test.rb +0 -105
  98. data/test/distributed_commands_on_sorted_sets_test.rb +0 -59
  99. data/test/distributed_commands_on_strings_test.rb +0 -79
  100. data/test/distributed_commands_on_value_types_test.rb +0 -129
  101. data/test/distributed_commands_requiring_clustering_test.rb +0 -162
  102. data/test/distributed_connection_handling_test.rb +0 -21
  103. data/test/distributed_internals_test.rb +0 -68
  104. data/test/distributed_key_tags_test.rb +0 -50
  105. data/test/distributed_persistence_control_commands_test.rb +0 -24
  106. data/test/distributed_publish_subscribe_test.rb +0 -90
  107. data/test/distributed_remote_server_control_commands_test.rb +0 -64
  108. data/test/distributed_scripting_test.rb +0 -100
  109. data/test/distributed_sorting_test.rb +0 -18
  110. data/test/distributed_test.rb +0 -56
  111. data/test/distributed_transactions_test.rb +0 -30
  112. data/test/encoding_test.rb +0 -14
  113. data/test/error_replies_test.rb +0 -57
  114. data/test/fork_safety_test.rb +0 -60
  115. data/test/helper.rb +0 -345
  116. data/test/helper_test.rb +0 -22
  117. data/test/internals_test.rb +0 -408
  118. data/test/lint/blocking_commands.rb +0 -174
  119. data/test/lint/hashes.rb +0 -203
  120. data/test/lint/hyper_log_log.rb +0 -74
  121. data/test/lint/lists.rb +0 -159
  122. data/test/lint/sets.rb +0 -282
  123. data/test/lint/sorted_sets.rb +0 -497
  124. data/test/lint/strings.rb +0 -348
  125. data/test/lint/value_types.rb +0 -130
  126. data/test/persistence_control_commands_test.rb +0 -24
  127. data/test/pipelining_commands_test.rb +0 -246
  128. data/test/publish_subscribe_test.rb +0 -280
  129. data/test/remote_server_control_commands_test.rb +0 -175
  130. data/test/scanning_test.rb +0 -407
  131. data/test/scripting_test.rb +0 -76
  132. data/test/sentinel_command_test.rb +0 -78
  133. data/test/sentinel_test.rb +0 -253
  134. data/test/sorting_test.rb +0 -57
  135. data/test/ssl_test.rb +0 -69
  136. data/test/support/cluster/orchestrator.rb +0 -199
  137. data/test/support/connection/hiredis.rb +0 -1
  138. data/test/support/connection/ruby.rb +0 -1
  139. data/test/support/connection/synchrony.rb +0 -17
  140. data/test/support/redis_mock.rb +0 -130
  141. data/test/support/ssl/gen_certs.sh +0 -31
  142. data/test/support/ssl/trusted-ca.crt +0 -25
  143. data/test/support/ssl/trusted-ca.key +0 -27
  144. data/test/support/ssl/trusted-cert.crt +0 -81
  145. data/test/support/ssl/trusted-cert.key +0 -28
  146. data/test/support/ssl/untrusted-ca.crt +0 -26
  147. data/test/support/ssl/untrusted-ca.key +0 -27
  148. data/test/support/ssl/untrusted-cert.crt +0 -82
  149. data/test/support/ssl/untrusted-cert.key +0 -28
  150. data/test/support/wire/synchrony.rb +0 -24
  151. data/test/support/wire/thread.rb +0 -5
  152. data/test/synchrony_driver.rb +0 -85
  153. data/test/test.conf.erb +0 -9
  154. data/test/thread_safety_test.rb +0 -60
  155. data/test/transactions_test.rb +0 -272
  156. data/test/unknown_commands_test.rb +0 -12
  157. data/test/url_param_test.rb +0 -136
@@ -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,8 +15,7 @@ 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)
@@ -24,97 +25,92 @@ class Redis
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
- def read(nbytes)
43
- result = @buffer.slice!(0, nbytes)
44
-
45
- while result.bytesize < nbytes
46
- result << _read_from_socket(nbytes - result.bytesize)
47
- end
48
-
49
- result
35
+ string_capacity_support = begin
36
+ String.new(capacity: 0)
37
+ true # Ruby 2.4+
38
+ rescue ArgumentError
39
+ false # Ruby 2.3
50
40
  end
51
41
 
52
- def gets
53
- crlf = nil
42
+ if string_capacity_support
43
+ def read(nbytes)
44
+ result = @buffer.slice!(0, nbytes)
54
45
 
55
- while (crlf = @buffer.index(CRLF)) == nil
56
- @buffer << _read_from_socket(1024)
57
- end
46
+ buffer = String.new(capacity: nbytes, encoding: Encoding::ASCII_8BIT)
47
+ result << _read_from_socket(nbytes - result.bytesize, buffer) while result.bytesize < nbytes
58
48
 
59
- @buffer.slice!(0, crlf + CRLF.bytesize)
60
- end
49
+ result
50
+ end
51
+ else
52
+ def read(nbytes)
53
+ result = @buffer.slice!(0, nbytes)
61
54
 
62
- def _read_from_socket(nbytes)
55
+ result << _read_from_socket(nbytes - result.bytesize, "".b) while result.bytesize < nbytes
63
56
 
64
- begin
65
- read_nonblock(nbytes)
57
+ result
58
+ end
59
+ end
66
60
 
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
61
+ def gets
62
+ while (crlf = @buffer.index(CRLF)).nil?
63
+ @buffer << _read_from_socket(16_384)
79
64
  end
80
65
 
81
- rescue EOFError
82
- raise Errno::ECONNRESET
66
+ @buffer.slice!(0, crlf + CRLF.bytesize)
83
67
  end
84
68
 
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
69
+ def _read_from_socket(nbytes, buffer = nil)
70
+ loop do
71
+ case chunk = read_nonblock(nbytes, buffer, exception: false)
72
+ when :wait_readable
73
+ unless wait_readable(@timeout)
74
+ raise Redis::TimeoutError
75
+ end
76
+ when :wait_writable
77
+ unless wait_writable(@timeout)
78
+ raise Redis::TimeoutError
79
+ end
80
+ when nil
81
+ raise Errno::ECONNRESET
82
+ when String
83
+ return chunk
100
84
  end
101
85
  end
102
-
103
- rescue EOFError
104
- raise Errno::ECONNRESET
105
86
  end
106
87
 
107
- def write(data)
108
- return super(data) unless @write_timeout
88
+ def write(buffer)
89
+ return super(buffer) unless @write_timeout
109
90
 
110
- length = data.bytesize
111
- total_count = 0
91
+ bytes_to_write = buffer.bytesize
92
+ total_bytes_written = 0
112
93
  loop do
113
- count = _write_to_socket(data)
94
+ case bytes_written = write_nonblock(buffer, exception: false)
95
+ when :wait_readable
96
+ unless wait_readable(@write_timeout)
97
+ raise Redis::TimeoutError
98
+ end
99
+ when :wait_writable
100
+ unless wait_writable(@write_timeout)
101
+ raise Redis::TimeoutError
102
+ end
103
+ when nil
104
+ raise Errno::ECONNRESET
105
+ when Integer
106
+ total_bytes_written += bytes_written
107
+
108
+ if total_bytes_written >= bytes_to_write
109
+ return total_bytes_written
110
+ end
114
111
 
115
- total_count += count
116
- return total_count if total_count >= length
117
- data = data.byteslice(count..-1)
112
+ buffer = buffer.byteslice(bytes_written..-1)
113
+ end
118
114
  end
119
115
  end
120
116
  end
@@ -124,7 +120,6 @@ class Redis
124
120
  require "timeout"
125
121
 
126
122
  class TCPSocket < ::TCPSocket
127
-
128
123
  include SocketMixin
129
124
 
130
125
  def self.connect(host, port, timeout)
@@ -140,7 +135,6 @@ class Redis
140
135
  if defined?(::UNIXSocket)
141
136
 
142
137
  class UNIXSocket < ::UNIXSocket
143
-
144
138
  include SocketMixin
145
139
 
146
140
  def self.connect(path, timeout)
@@ -152,13 +146,12 @@ class Redis
152
146
  raise TimeoutError
153
147
  end
154
148
 
155
- # JRuby raises Errno::EAGAIN on #read_nonblock even when IO.select
149
+ # JRuby raises Errno::EAGAIN on #read_nonblock even when it
156
150
  # says it is readable (1.6.6, in both 1.8 and 1.9 mode).
157
151
  # Use the blocking #readpartial method instead.
158
152
 
159
153
  def _read_from_socket(nbytes)
160
154
  readpartial(nbytes)
161
-
162
155
  rescue EOFError
163
156
  raise Errno::ECONNRESET
164
157
  end
@@ -169,19 +162,16 @@ class Redis
169
162
  else
170
163
 
171
164
  class TCPSocket < ::Socket
172
-
173
165
  include SocketMixin
174
166
 
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])
167
+ def self.connect_addrinfo(addrinfo, port, timeout)
168
+ sock = new(::Socket.const_get(addrinfo[0]), Socket::SOCK_STREAM, 0)
169
+ sockaddr = ::Socket.pack_sockaddr_in(port, addrinfo[3])
178
170
 
179
171
  begin
180
172
  sock.connect_nonblock(sockaddr)
181
173
  rescue Errno::EINPROGRESS
182
- if IO.select(nil, [sock], nil, timeout) == nil
183
- raise TimeoutError
184
- end
174
+ raise TimeoutError unless sock.wait_writable(timeout)
185
175
 
186
176
  begin
187
177
  sock.connect_nonblock(sockaddr)
@@ -220,14 +210,13 @@ class Redis
220
210
  return connect_addrinfo(ai, port, timeout)
221
211
  rescue SystemCallError
222
212
  # Raise if this was our last attempt.
223
- raise if addrinfo.length == i+1
213
+ raise if addrinfo.length == i + 1
224
214
  end
225
215
  end
226
216
  end
227
217
  end
228
218
 
229
219
  class UNIXSocket < ::Socket
230
-
231
220
  include SocketMixin
232
221
 
233
222
  def self.connect(path, timeout)
@@ -237,9 +226,7 @@ class Redis
237
226
  begin
238
227
  sock.connect_nonblock(sockaddr)
239
228
  rescue Errno::EINPROGRESS
240
- if IO.select(nil, [sock], nil, timeout) == nil
241
- raise TimeoutError
242
- end
229
+ raise TimeoutError unless sock.wait_writable(timeout)
243
230
 
244
231
  begin
245
232
  sock.connect_nonblock(sockaddr)
@@ -257,18 +244,56 @@ class Redis
257
244
  class SSLSocket < ::OpenSSL::SSL::SSLSocket
258
245
  include SocketMixin
259
246
 
247
+ unless method_defined?(:wait_readable)
248
+ def wait_readable(timeout = nil)
249
+ to_io.wait_readable(timeout)
250
+ end
251
+ end
252
+
253
+ unless method_defined?(:wait_writable)
254
+ def wait_writable(timeout = nil)
255
+ to_io.wait_writable(timeout)
256
+ end
257
+ end
258
+
260
259
  def self.connect(host, port, timeout, ssl_params)
261
260
  # Note: this is using Redis::Connection::TCPSocket
262
261
  tcp_sock = TCPSocket.connect(host, port, timeout)
263
262
 
264
263
  ctx = OpenSSL::SSL::SSLContext.new
265
- ctx.set_params(ssl_params) if ssl_params && !ssl_params.empty?
264
+
265
+ # The provided parameters are merged into OpenSSL::SSL::SSLContext::DEFAULT_PARAMS
266
+ ctx.set_params(ssl_params || {})
266
267
 
267
268
  ssl_sock = new(tcp_sock, ctx)
268
269
  ssl_sock.hostname = host
269
- ssl_sock.connect
270
270
 
271
- unless ctx.verify_mode == OpenSSL::SSL::VERIFY_NONE
271
+ begin
272
+ # Initiate the socket connection in the background. If it doesn't fail
273
+ # immediately it will raise an IO::WaitWritable (Errno::EINPROGRESS)
274
+ # indicating the connection is in progress.
275
+ # Unlike waiting for a tcp socket to connect, you can't time out ssl socket
276
+ # connections during the connect phase properly, because IO.select only partially works.
277
+ # Instead, you have to retry.
278
+ ssl_sock.connect_nonblock
279
+ rescue Errno::EAGAIN, Errno::EWOULDBLOCK, IO::WaitReadable
280
+ if ssl_sock.wait_readable(timeout)
281
+ retry
282
+ else
283
+ raise TimeoutError
284
+ end
285
+ rescue IO::WaitWritable
286
+ if ssl_sock.wait_writable(timeout)
287
+ retry
288
+ else
289
+ raise TimeoutError
290
+ end
291
+ end
292
+
293
+ unless ctx.verify_mode == OpenSSL::SSL::VERIFY_NONE || (
294
+ ctx.respond_to?(:verify_hostname) &&
295
+ !ctx.verify_hostname
296
+ )
272
297
  ssl_sock.post_connection_check(host)
273
298
  end
274
299
 
@@ -280,15 +305,16 @@ class Redis
280
305
  class Ruby
281
306
  include Redis::Connection::CommandHelper
282
307
 
283
- MINUS = "-".freeze
284
- PLUS = "+".freeze
285
- COLON = ":".freeze
286
- DOLLAR = "$".freeze
287
- ASTERISK = "*".freeze
308
+ MINUS = "-"
309
+ PLUS = "+"
310
+ COLON = ":"
311
+ DOLLAR = "$"
312
+ ASTERISK = "*"
288
313
 
289
314
  def self.connect(config)
290
315
  if config[:scheme] == "unix"
291
316
  raise ArgumentError, "SSL incompatible with unix sockets" if config[:ssl]
317
+
292
318
  sock = UNIXSocket.connect(config[:path], config[:connect_timeout])
293
319
  elsif config[:scheme] == "rediss" || config[:ssl]
294
320
  sock = SSLSocket.connect(config[:host], config[:port], config[:connect_timeout], config[:ssl_params])
@@ -300,10 +326,11 @@ class Redis
300
326
  instance.timeout = config[:read_timeout]
301
327
  instance.write_timeout = config[:write_timeout]
302
328
  instance.set_tcp_keepalive config[:tcp_keepalive]
329
+ instance.set_tcp_nodelay if sock.is_a? TCPSocket
303
330
  instance
304
331
  end
305
332
 
306
- if [:SOL_SOCKET, :SO_KEEPALIVE, :SOL_TCP, :TCP_KEEPIDLE, :TCP_KEEPINTVL, :TCP_KEEPCNT].all?{|c| Socket.const_defined? c}
333
+ if %i[SOL_SOCKET SO_KEEPALIVE SOL_TCP TCP_KEEPIDLE TCP_KEEPINTVL TCP_KEEPCNT].all? { |c| Socket.const_defined? c }
307
334
  def set_tcp_keepalive(keepalive)
308
335
  return unless keepalive.is_a?(Hash)
309
336
 
@@ -315,14 +342,13 @@ class Redis
315
342
 
316
343
  def get_tcp_keepalive
317
344
  {
318
- :time => @sock.getsockopt(Socket::SOL_TCP, Socket::TCP_KEEPIDLE).int,
319
- :intvl => @sock.getsockopt(Socket::SOL_TCP, Socket::TCP_KEEPINTVL).int,
320
- :probes => @sock.getsockopt(Socket::SOL_TCP, Socket::TCP_KEEPCNT).int,
345
+ time: @sock.getsockopt(Socket::SOL_TCP, Socket::TCP_KEEPIDLE).int,
346
+ intvl: @sock.getsockopt(Socket::SOL_TCP, Socket::TCP_KEEPINTVL).int,
347
+ probes: @sock.getsockopt(Socket::SOL_TCP, Socket::TCP_KEEPCNT).int
321
348
  }
322
349
  end
323
350
  else
324
- def set_tcp_keepalive(keepalive)
325
- end
351
+ def set_tcp_keepalive(keepalive); end
326
352
 
327
353
  def get_tcp_keepalive
328
354
  {
@@ -330,12 +356,21 @@ class Redis
330
356
  end
331
357
  end
332
358
 
359
+ # disables Nagle's Algorithm, prevents multiple round trips with MULTI
360
+ if %i[IPPROTO_TCP TCP_NODELAY].all? { |c| Socket.const_defined? c }
361
+ def set_tcp_nodelay
362
+ @sock.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
363
+ end
364
+ else
365
+ def set_tcp_nodelay; end
366
+ end
367
+
333
368
  def initialize(sock)
334
369
  @sock = sock
335
370
  end
336
371
 
337
372
  def connected?
338
- !! @sock
373
+ !!@sock
339
374
  end
340
375
 
341
376
  def disconnect
@@ -346,9 +381,7 @@ class Redis
346
381
  end
347
382
 
348
383
  def timeout=(timeout)
349
- if @sock.respond_to?(:timeout=)
350
- @sock.timeout = timeout
351
- end
384
+ @sock.timeout = timeout if @sock.respond_to?(:timeout=)
352
385
  end
353
386
 
354
387
  def write_timeout=(timeout)
@@ -363,7 +396,6 @@ class Redis
363
396
  line = @sock.gets
364
397
  reply_type = line.slice!(0, 1)
365
398
  format_reply(reply_type, line)
366
-
367
399
  rescue Errno::EAGAIN
368
400
  raise TimeoutError
369
401
  end
@@ -375,7 +407,7 @@ class Redis
375
407
  when COLON then format_integer_reply(line)
376
408
  when DOLLAR then format_bulk_reply(line)
377
409
  when ASTERISK then format_multi_bulk_reply(line)
378
- else raise ProtocolError.new(reply_type)
410
+ else raise ProtocolError, reply_type
379
411
  end
380
412
  end
381
413
 
@@ -394,6 +426,7 @@ class Redis
394
426
  def format_bulk_reply(line)
395
427
  bulklen = line.to_i
396
428
  return if bulklen == -1
429
+
397
430
  reply = encode(@sock.read(bulklen))
398
431
  @sock.read(2) # Discard CRLF.
399
432
  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
 
@@ -105,7 +110,7 @@ class Redis
105
110
  end
106
111
 
107
112
  def connected?
108
- @connection && @connection.connected?
113
+ @connection&.connected?
109
114
  end
110
115
 
111
116
  def timeout=(timeout)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative "connection/registry"
2
4
 
3
5
  # If a connection driver was required before this file, the array