redis 4.1.4 → 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.
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'set'
4
-
5
3
  class Redis
6
4
  class Cluster
7
5
  # Keep slot and node key map for Redis Cluster Client
@@ -28,11 +26,20 @@ class Redis
28
26
  return nil unless exists?(slot)
29
27
  return find_node_key_of_master(slot) if replica_disabled?
30
28
 
31
- @map[slot][:slaves].to_a.sample
29
+ @map[slot][:slaves].sample
32
30
  end
33
31
 
34
32
  def put(slot, node_key)
35
- assign_node_key(@map, slot, node_key)
33
+ # Since we're sharing a hash for build_slot_node_key_map, duplicate it
34
+ # if it already exists instead of preserving as-is.
35
+ @map[slot] = @map[slot] ? @map[slot].dup : { master: nil, slaves: [] }
36
+
37
+ if master?(node_key)
38
+ @map[slot][:master] = node_key
39
+ elsif !@map[slot][:slaves].include?(node_key)
40
+ @map[slot][:slaves] << node_key
41
+ end
42
+
36
43
  nil
37
44
  end
38
45
 
@@ -52,20 +59,27 @@ class Redis
52
59
 
53
60
  # available_slots is mapping of node_key to list of slot ranges
54
61
  def build_slot_node_key_map(available_slots)
55
- available_slots.each_with_object({}) do |(node_key, slots_arr), acc|
56
- slots_arr.each do |slots|
57
- slots.each { |slot| assign_node_key(acc, slot, node_key) }
62
+ by_ranges = {}
63
+ available_slots.each do |node_key, slots_arr|
64
+ by_ranges[slots_arr] ||= { master: nil, slaves: [] }
65
+
66
+ if master?(node_key)
67
+ by_ranges[slots_arr][:master] = node_key
68
+ elsif !by_ranges[slots_arr][:slaves].include?(node_key)
69
+ by_ranges[slots_arr][:slaves] << node_key
58
70
  end
59
71
  end
60
- end
61
72
 
62
- def assign_node_key(mappings, slot, node_key)
63
- mappings[slot] ||= { master: nil, slaves: ::Set.new }
64
- if master?(node_key)
65
- mappings[slot][:master] = node_key
66
- else
67
- mappings[slot][:slaves].add(node_key)
73
+ by_slot = {}
74
+ by_ranges.each do |slots_arr, nodes|
75
+ slots_arr.each do |slots|
76
+ slots.each do |slot|
77
+ by_slot[slot] = nodes
78
+ end
79
+ end
68
80
  end
81
+
82
+ by_slot
69
83
  end
70
84
  end
71
85
  end
@@ -25,9 +25,8 @@ class Redis
25
25
  def fetch_slot_info(node)
26
26
  hash_with_default_arr = Hash.new { |h, k| h[k] = [] }
27
27
  node.call(%i[cluster slots])
28
- .flat_map { |arr| parse_slot_info(arr, default_ip: node.host) }
29
- .each_with_object(hash_with_default_arr) { |arr, h| h[arr[0]] << arr[1] }
30
-
28
+ .flat_map { |arr| parse_slot_info(arr, default_ip: node.host) }
29
+ .each_with_object(hash_with_default_arr) { |arr, h| h[arr[0]] << arr[1] }
31
30
  rescue CannotConnectError, ConnectionError, CommandError
32
31
  {} # can retry on another node
33
32
  end
data/lib/redis/cluster.rb CHANGED
@@ -78,10 +78,13 @@ class Redis
78
78
  end
79
79
 
80
80
  def call_pipeline(pipeline)
81
- node_keys, command_keys = extract_keys_in_pipeline(pipeline)
82
- raise CrossSlotPipeliningError, command_keys if node_keys.size > 1
83
- node = find_node(node_keys.first)
84
- try_send(node, :call_pipeline, pipeline)
81
+ node_keys = pipeline.commands.map { |cmd| find_node_key(cmd, primary_only: true) }.compact.uniq
82
+ if node_keys.size > 1
83
+ raise(CrossSlotPipeliningError,
84
+ pipeline.commands.map { |cmd| @command.extract_first_key(cmd) }.reject(&:empty?).uniq)
85
+ end
86
+
87
+ try_send(find_node(node_keys.first), :call_pipeline, pipeline)
85
88
  end
86
89
 
87
90
  def call_with_timeout(command, timeout, &block)
@@ -127,7 +130,7 @@ class Redis
127
130
  def send_command(command, &block)
128
131
  cmd = command.first.to_s.downcase
129
132
  case cmd
130
- when 'auth', 'bgrewriteaof', 'bgsave', 'quit', 'save'
133
+ when 'acl', 'auth', 'bgrewriteaof', 'bgsave', 'quit', 'save'
131
134
  @node.call_all(command, &block).first
132
135
  when 'flushall', 'flushdb'
133
136
  @node.call_master(command, &block).first
@@ -216,11 +219,13 @@ class Redis
216
219
  rescue CommandError => err
217
220
  if err.message.start_with?('MOVED')
218
221
  raise if retry_count <= 0
222
+
219
223
  node = assign_redirection_node(err.message)
220
224
  retry_count -= 1
221
225
  retry
222
226
  elsif err.message.start_with?('ASK')
223
227
  raise if retry_count <= 0
228
+
224
229
  node = assign_asking_node(err.message)
225
230
  node.call(%i[asking])
226
231
  retry_count -= 1
@@ -250,14 +255,14 @@ class Redis
250
255
  find_node(node_key)
251
256
  end
252
257
 
253
- def find_node_key(command)
258
+ def find_node_key(command, primary_only: false)
254
259
  key = @command.extract_first_key(command)
255
260
  return if key.empty?
256
261
 
257
262
  slot = KeySlotConverter.convert(key)
258
263
  return unless @slot.exists?(slot)
259
264
 
260
- if @command.should_send_to_master?(command)
265
+ if @command.should_send_to_master?(command) || primary_only
261
266
  @slot.find_node_key_of_master(slot)
262
267
  else
263
268
  @slot.find_node_key_of_slave(slot)
@@ -266,6 +271,7 @@ class Redis
266
271
 
267
272
  def find_node(node_key)
268
273
  return @node.sample if node_key.nil?
274
+
269
275
  @node.find_by(node_key)
270
276
  rescue Node::ReloadNeeded
271
277
  update_cluster_info!(node_key)
@@ -281,11 +287,5 @@ class Redis
281
287
  @node.map(&:disconnect)
282
288
  @node, @slot = fetch_cluster_info!(@option)
283
289
  end
284
-
285
- def extract_keys_in_pipeline(pipeline)
286
- node_keys = pipeline.commands.map { |cmd| find_node_key(cmd) }.compact.uniq
287
- command_keys = pipeline.commands.map { |cmd| @command.extract_first_key(cmd) }.reject(&:empty?)
288
- [node_keys, command_keys]
289
- end
290
290
  end
291
291
  end
@@ -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)
@@ -12,11 +12,13 @@ class Redis
12
12
  if i.is_a? Array
13
13
  i.each do |j|
14
14
  j = j.to_s
15
+ j = j.encoding == Encoding::BINARY ? j : j.b
15
16
  command << "$#{j.bytesize}"
16
17
  command << j
17
18
  end
18
19
  else
19
20
  i = i.to_s
21
+ i = i.encoding == Encoding::BINARY ? i : i.b
20
22
  command << "$#{i.bytesize}"
21
23
  command << i
22
24
  end
@@ -29,7 +31,7 @@ class Redis
29
31
  command.join(COMMAND_DELIMITER)
30
32
  end
31
33
 
32
- protected
34
+ protected
33
35
 
34
36
  def encode(string)
35
37
  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,108 +15,85 @@ 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)
22
22
 
23
23
  @timeout = @write_timeout = nil
24
- @buffer = "".dup
24
+ @buffer = "".b
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
+ buffer = String.new(capacity: nbytes, encoding: Encoding::ASCII_8BIT)
39
+ result << _read_from_socket(nbytes - result.bytesize, buffer) while result.bytesize < nbytes
49
40
 
50
41
  result
51
42
  end
52
43
 
53
44
  def gets
54
- crlf = nil
55
-
56
- while (crlf = @buffer.index(CRLF)) == nil
57
- @buffer << _read_from_socket(16384)
45
+ while (crlf = @buffer.index(CRLF)).nil?
46
+ @buffer << _read_from_socket(16_384)
58
47
  end
59
48
 
60
49
  @buffer.slice!(0, crlf + CRLF.bytesize)
61
50
  end
62
51
 
63
- 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
79
- end
80
- end
81
-
82
- rescue EOFError
83
- raise Errno::ECONNRESET
84
- end
85
-
86
- 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
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
101
67
  end
102
68
  end
103
-
104
- rescue EOFError
105
- raise Errno::ECONNRESET
106
69
  end
107
70
 
108
- def write(data)
109
- return super(data) unless @write_timeout
71
+ def write(buffer)
72
+ return super(buffer) unless @write_timeout
110
73
 
111
- length = data.bytesize
112
- total_count = 0
74
+ bytes_to_write = buffer.bytesize
75
+ total_bytes_written = 0
113
76
  loop do
114
- count = _write_to_socket(data)
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
115
90
 
116
- total_count += count
117
- return total_count if total_count >= length
118
- data = data.byteslice(count..-1)
91
+ if total_bytes_written >= bytes_to_write
92
+ return total_bytes_written
93
+ end
94
+
95
+ buffer = buffer.byteslice(bytes_written..-1)
96
+ end
119
97
  end
120
98
  end
121
99
  end
@@ -125,7 +103,6 @@ class Redis
125
103
  require "timeout"
126
104
 
127
105
  class TCPSocket < ::TCPSocket
128
-
129
106
  include SocketMixin
130
107
 
131
108
  def self.connect(host, port, timeout)
@@ -141,7 +118,6 @@ class Redis
141
118
  if defined?(::UNIXSocket)
142
119
 
143
120
  class UNIXSocket < ::UNIXSocket
144
-
145
121
  include SocketMixin
146
122
 
147
123
  def self.connect(path, timeout)
@@ -153,13 +129,12 @@ class Redis
153
129
  raise TimeoutError
154
130
  end
155
131
 
156
- # JRuby raises Errno::EAGAIN on #read_nonblock even when IO.select
132
+ # JRuby raises Errno::EAGAIN on #read_nonblock even when it
157
133
  # says it is readable (1.6.6, in both 1.8 and 1.9 mode).
158
134
  # Use the blocking #readpartial method instead.
159
135
 
160
136
  def _read_from_socket(nbytes)
161
137
  readpartial(nbytes)
162
-
163
138
  rescue EOFError
164
139
  raise Errno::ECONNRESET
165
140
  end
@@ -170,19 +145,16 @@ class Redis
170
145
  else
171
146
 
172
147
  class TCPSocket < ::Socket
173
-
174
148
  include SocketMixin
175
149
 
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])
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])
179
153
 
180
154
  begin
181
155
  sock.connect_nonblock(sockaddr)
182
156
  rescue Errno::EINPROGRESS
183
- if IO.select(nil, [sock], nil, timeout) == nil
184
- raise TimeoutError
185
- end
157
+ raise TimeoutError unless sock.wait_writable(timeout)
186
158
 
187
159
  begin
188
160
  sock.connect_nonblock(sockaddr)
@@ -221,14 +193,13 @@ class Redis
221
193
  return connect_addrinfo(ai, port, timeout)
222
194
  rescue SystemCallError
223
195
  # Raise if this was our last attempt.
224
- raise if addrinfo.length == i+1
196
+ raise if addrinfo.length == i + 1
225
197
  end
226
198
  end
227
199
  end
228
200
  end
229
201
 
230
202
  class UNIXSocket < ::Socket
231
-
232
203
  include SocketMixin
233
204
 
234
205
  def self.connect(path, timeout)
@@ -238,9 +209,7 @@ class Redis
238
209
  begin
239
210
  sock.connect_nonblock(sockaddr)
240
211
  rescue Errno::EINPROGRESS
241
- if IO.select(nil, [sock], nil, timeout) == nil
242
- raise TimeoutError
243
- end
212
+ raise TimeoutError unless sock.wait_writable(timeout)
244
213
 
245
214
  begin
246
215
  sock.connect_nonblock(sockaddr)
@@ -258,12 +227,26 @@ class Redis
258
227
  class SSLSocket < ::OpenSSL::SSL::SSLSocket
259
228
  include SocketMixin
260
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
+
261
242
  def self.connect(host, port, timeout, ssl_params)
262
243
  # Note: this is using Redis::Connection::TCPSocket
263
244
  tcp_sock = TCPSocket.connect(host, port, timeout)
264
245
 
265
246
  ctx = OpenSSL::SSL::SSLContext.new
266
- ctx.set_params(ssl_params) if ssl_params && !ssl_params.empty?
247
+
248
+ # The provided parameters are merged into OpenSSL::SSL::SSLContext::DEFAULT_PARAMS
249
+ ctx.set_params(ssl_params || {})
267
250
 
268
251
  ssl_sock = new(tcp_sock, ctx)
269
252
  ssl_sock.hostname = host
@@ -277,20 +260,23 @@ class Redis
277
260
  # Instead, you have to retry.
278
261
  ssl_sock.connect_nonblock
279
262
  rescue Errno::EAGAIN, Errno::EWOULDBLOCK, IO::WaitReadable
280
- if IO.select([ssl_sock], nil, nil, timeout)
263
+ if ssl_sock.wait_readable(timeout)
281
264
  retry
282
265
  else
283
266
  raise TimeoutError
284
267
  end
285
268
  rescue IO::WaitWritable
286
- if IO.select(nil, [ssl_sock], nil, timeout)
269
+ if ssl_sock.wait_writable(timeout)
287
270
  retry
288
271
  else
289
272
  raise TimeoutError
290
273
  end
291
274
  end
292
275
 
293
- unless ctx.verify_mode == OpenSSL::SSL::VERIFY_NONE || (ctx.respond_to?(:verify_hostname) && !ctx.verify_hostname)
276
+ unless ctx.verify_mode == OpenSSL::SSL::VERIFY_NONE || (
277
+ ctx.respond_to?(:verify_hostname) &&
278
+ !ctx.verify_hostname
279
+ )
294
280
  ssl_sock.post_connection_check(host)
295
281
  end
296
282
 
@@ -302,15 +288,16 @@ class Redis
302
288
  class Ruby
303
289
  include Redis::Connection::CommandHelper
304
290
 
305
- MINUS = "-".freeze
306
- PLUS = "+".freeze
307
- COLON = ":".freeze
308
- DOLLAR = "$".freeze
309
- ASTERISK = "*".freeze
291
+ MINUS = "-"
292
+ PLUS = "+"
293
+ COLON = ":"
294
+ DOLLAR = "$"
295
+ ASTERISK = "*"
310
296
 
311
297
  def self.connect(config)
312
298
  if config[:scheme] == "unix"
313
299
  raise ArgumentError, "SSL incompatible with unix sockets" if config[:ssl]
300
+
314
301
  sock = UNIXSocket.connect(config[:path], config[:connect_timeout])
315
302
  elsif config[:scheme] == "rediss" || config[:ssl]
316
303
  sock = SSLSocket.connect(config[:host], config[:port], config[:connect_timeout], config[:ssl_params])
@@ -326,7 +313,7 @@ class Redis
326
313
  instance
327
314
  end
328
315
 
329
- if [:SOL_SOCKET, :SO_KEEPALIVE, :SOL_TCP, :TCP_KEEPIDLE, :TCP_KEEPINTVL, :TCP_KEEPCNT].all?{|c| Socket.const_defined? c}
316
+ if %i[SOL_SOCKET SO_KEEPALIVE SOL_TCP TCP_KEEPIDLE TCP_KEEPINTVL TCP_KEEPCNT].all? { |c| Socket.const_defined? c }
330
317
  def set_tcp_keepalive(keepalive)
331
318
  return unless keepalive.is_a?(Hash)
332
319
 
@@ -338,14 +325,13 @@ class Redis
338
325
 
339
326
  def get_tcp_keepalive
340
327
  {
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,
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
344
331
  }
345
332
  end
346
333
  else
347
- def set_tcp_keepalive(keepalive)
348
- end
334
+ def set_tcp_keepalive(keepalive); end
349
335
 
350
336
  def get_tcp_keepalive
351
337
  {
@@ -354,13 +340,12 @@ class Redis
354
340
  end
355
341
 
356
342
  # disables Nagle's Algorithm, prevents multiple round trips with MULTI
357
- if [:IPPROTO_TCP, :TCP_NODELAY].all?{|c| Socket.const_defined? c}
343
+ if %i[IPPROTO_TCP TCP_NODELAY].all? { |c| Socket.const_defined? c }
358
344
  def set_tcp_nodelay
359
345
  @sock.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
360
346
  end
361
347
  else
362
- def set_tcp_nodelay
363
- end
348
+ def set_tcp_nodelay; end
364
349
  end
365
350
 
366
351
  def initialize(sock)
@@ -368,7 +353,7 @@ class Redis
368
353
  end
369
354
 
370
355
  def connected?
371
- !! @sock
356
+ !!@sock
372
357
  end
373
358
 
374
359
  def disconnect
@@ -379,9 +364,7 @@ class Redis
379
364
  end
380
365
 
381
366
  def timeout=(timeout)
382
- if @sock.respond_to?(:timeout=)
383
- @sock.timeout = timeout
384
- end
367
+ @sock.timeout = timeout if @sock.respond_to?(:timeout=)
385
368
  end
386
369
 
387
370
  def write_timeout=(timeout)
@@ -396,7 +379,6 @@ class Redis
396
379
  line = @sock.gets
397
380
  reply_type = line.slice!(0, 1)
398
381
  format_reply(reply_type, line)
399
-
400
382
  rescue Errno::EAGAIN
401
383
  raise TimeoutError
402
384
  end
@@ -408,7 +390,7 @@ class Redis
408
390
  when COLON then format_integer_reply(line)
409
391
  when DOLLAR then format_bulk_reply(line)
410
392
  when ASTERISK then format_multi_bulk_reply(line)
411
- else raise ProtocolError.new(reply_type)
393
+ else raise ProtocolError, reply_type
412
394
  end
413
395
  end
414
396
 
@@ -427,6 +409,7 @@ class Redis
427
409
  def format_bulk_reply(line)
428
410
  bulklen = line.to_i
429
411
  return if bulklen == -1
412
+
430
413
  reply = encode(@sock.read(bulklen))
431
414
  @sock.read(2) # Discard CRLF.
432
415
  reply
@@ -1,10 +1,16 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require_relative "command_helper"
3
4
  require_relative "registry"
4
5
  require_relative "../errors"
5
6
  require "em-synchrony"
6
7
  require "hiredis/reader"
7
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
+
8
14
  class Redis
9
15
  module Connection
10
16
  class RedisClient < EventMachine::Connection
@@ -47,9 +53,7 @@ class Redis
47
53
 
48
54
  def read
49
55
  @req = EventMachine::DefaultDeferrable.new
50
- if @timeout > 0
51
- @req.timeout(@timeout, :timeout)
52
- end
56
+ @req.timeout(@timeout, :timeout) if @timeout > 0
53
57
  EventMachine::Synchrony.sync @req
54
58
  end
55
59
 
@@ -106,7 +110,7 @@ class Redis
106
110
  end
107
111
 
108
112
  def connected?
109
- @connection && @connection.connected?
113
+ @connection&.connected?
110
114
  end
111
115
 
112
116
  def timeout=(timeout)
@@ -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