redis 4.0.0.rc1 → 4.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +164 -3
  3. data/README.md +127 -18
  4. data/lib/redis/client.rb +164 -93
  5. data/lib/redis/cluster/command.rb +81 -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 +108 -0
  9. data/lib/redis/cluster/node_key.rb +31 -0
  10. data/lib/redis/cluster/node_loader.rb +37 -0
  11. data/lib/redis/cluster/option.rb +93 -0
  12. data/lib/redis/cluster/slot.rb +86 -0
  13. data/lib/redis/cluster/slot_loader.rb +49 -0
  14. data/lib/redis/cluster.rb +291 -0
  15. data/lib/redis/connection/command_helper.rb +5 -2
  16. data/lib/redis/connection/hiredis.rb +4 -3
  17. data/lib/redis/connection/registry.rb +2 -1
  18. data/lib/redis/connection/ruby.rb +125 -106
  19. data/lib/redis/connection/synchrony.rb +18 -5
  20. data/lib/redis/connection.rb +2 -0
  21. data/lib/redis/distributed.rb +995 -0
  22. data/lib/redis/errors.rb +48 -0
  23. data/lib/redis/hash_ring.rb +89 -0
  24. data/lib/redis/pipeline.rb +55 -9
  25. data/lib/redis/subscribe.rb +11 -12
  26. data/lib/redis/version.rb +3 -1
  27. data/lib/redis.rb +1433 -381
  28. metadata +34 -141
  29. data/.gitignore +0 -16
  30. data/.travis/Gemfile +0 -11
  31. data/.travis.yml +0 -71
  32. data/.yardopts +0 -3
  33. data/Gemfile +0 -3
  34. data/benchmarking/logging.rb +0 -71
  35. data/benchmarking/pipeline.rb +0 -51
  36. data/benchmarking/speed.rb +0 -21
  37. data/benchmarking/suite.rb +0 -24
  38. data/benchmarking/worker.rb +0 -71
  39. data/examples/basic.rb +0 -15
  40. data/examples/consistency.rb +0 -114
  41. data/examples/incr-decr.rb +0 -17
  42. data/examples/list.rb +0 -26
  43. data/examples/pubsub.rb +0 -37
  44. data/examples/sentinel/sentinel.conf +0 -9
  45. data/examples/sentinel/start +0 -49
  46. data/examples/sentinel.rb +0 -41
  47. data/examples/sets.rb +0 -36
  48. data/examples/unicorn/config.ru +0 -3
  49. data/examples/unicorn/unicorn.rb +0 -20
  50. data/makefile +0 -42
  51. data/redis.gemspec +0 -40
  52. data/test/bitpos_test.rb +0 -63
  53. data/test/blocking_commands_test.rb +0 -183
  54. data/test/client_test.rb +0 -59
  55. data/test/command_map_test.rb +0 -28
  56. data/test/commands_on_hashes_test.rb +0 -174
  57. data/test/commands_on_hyper_log_log_test.rb +0 -70
  58. data/test/commands_on_lists_test.rb +0 -154
  59. data/test/commands_on_sets_test.rb +0 -208
  60. data/test/commands_on_sorted_sets_test.rb +0 -444
  61. data/test/commands_on_strings_test.rb +0 -338
  62. data/test/commands_on_value_types_test.rb +0 -246
  63. data/test/connection_handling_test.rb +0 -275
  64. data/test/db/.gitkeep +0 -0
  65. data/test/encoding_test.rb +0 -14
  66. data/test/error_replies_test.rb +0 -57
  67. data/test/fork_safety_test.rb +0 -60
  68. data/test/helper.rb +0 -179
  69. data/test/helper_test.rb +0 -22
  70. data/test/internals_test.rb +0 -435
  71. data/test/persistence_control_commands_test.rb +0 -24
  72. data/test/pipelining_commands_test.rb +0 -238
  73. data/test/publish_subscribe_test.rb +0 -280
  74. data/test/remote_server_control_commands_test.rb +0 -175
  75. data/test/scanning_test.rb +0 -407
  76. data/test/scripting_test.rb +0 -76
  77. data/test/sentinel_command_test.rb +0 -78
  78. data/test/sentinel_test.rb +0 -253
  79. data/test/sorting_test.rb +0 -57
  80. data/test/ssl_test.rb +0 -69
  81. data/test/support/connection/hiredis.rb +0 -1
  82. data/test/support/connection/ruby.rb +0 -1
  83. data/test/support/connection/synchrony.rb +0 -17
  84. data/test/support/redis_mock.rb +0 -130
  85. data/test/support/ssl/gen_certs.sh +0 -31
  86. data/test/support/ssl/trusted-ca.crt +0 -25
  87. data/test/support/ssl/trusted-ca.key +0 -27
  88. data/test/support/ssl/trusted-cert.crt +0 -81
  89. data/test/support/ssl/trusted-cert.key +0 -28
  90. data/test/support/ssl/untrusted-ca.crt +0 -26
  91. data/test/support/ssl/untrusted-ca.key +0 -27
  92. data/test/support/ssl/untrusted-cert.crt +0 -82
  93. data/test/support/ssl/untrusted-cert.key +0 -28
  94. data/test/support/wire/synchrony.rb +0 -24
  95. data/test/support/wire/thread.rb +0 -5
  96. data/test/synchrony_driver.rb +0 -85
  97. data/test/test.conf.erb +0 -9
  98. data/test/thread_safety_test.rb +0 -60
  99. data/test/transactions_test.rb +0 -262
  100. data/test/unknown_commands_test.rb +0 -12
  101. data/test/url_param_test.rb +0 -136
@@ -1,7 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Redis
2
4
  module Connection
3
5
  module CommandHelper
4
-
5
6
  COMMAND_DELIMITER = "\r\n"
6
7
 
7
8
  def build_command(args)
@@ -11,11 +12,13 @@ class Redis
11
12
  if i.is_a? Array
12
13
  i.each do |j|
13
14
  j = j.to_s
15
+ j = j.encoding == Encoding::BINARY ? j : j.b
14
16
  command << "$#{j.bytesize}"
15
17
  command << j
16
18
  end
17
19
  else
18
20
  i = i.to_s
21
+ i = i.encoding == Encoding::BINARY ? i : i.b
19
22
  command << "$#{i.bytesize}"
20
23
  command << i
21
24
  end
@@ -28,7 +31,7 @@ class Redis
28
31
  command.join(COMMAND_DELIMITER)
29
32
  end
30
33
 
31
- protected
34
+ protected
32
35
 
33
36
  def encode(string)
34
37
  string.force_encoding(Encoding.default_external)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative "registry"
2
4
  require_relative "../errors"
3
5
  require "hiredis/connection"
@@ -6,7 +8,6 @@ require "timeout"
6
8
  class Redis
7
9
  module Connection
8
10
  class Hiredis
9
-
10
11
  def self.connect(config)
11
12
  connection = ::Hiredis::Connection.new
12
13
  connect_timeout = (config.fetch(:connect_timeout, 0) * 1_000_000).to_i
@@ -31,7 +32,7 @@ class Redis
31
32
  end
32
33
 
33
34
  def connected?
34
- @connection && @connection.connected?
35
+ @connection&.connected?
35
36
  end
36
37
 
37
38
  def timeout=(timeout)
@@ -57,7 +58,7 @@ class Redis
57
58
  rescue Errno::EAGAIN
58
59
  raise TimeoutError
59
60
  rescue RuntimeError => err
60
- raise ProtocolError.new(err.message)
61
+ raise ProtocolError, err.message
61
62
  end
62
63
  end
63
64
  end
@@ -1,6 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Redis
2
4
  module Connection
3
-
4
5
  # Store a list of loaded connection drivers in the Connection module.
5
6
  # Redis::Client uses the last required driver by default, and will be aware
6
7
  # of the loaded connection drivers if the user chooses to override the
@@ -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,108 +15,85 @@ 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)
21
22
 
22
23
  @timeout = @write_timeout = nil
23
- @buffer = ""
24
+ @buffer = "".b
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
35
  def read(nbytes)
43
36
  result = @buffer.slice!(0, nbytes)
44
37
 
45
- while result.bytesize < nbytes
46
- result << _read_from_socket(nbytes - result.bytesize)
47
- end
38
+ buffer = String.new(capacity: nbytes, encoding: Encoding::ASCII_8BIT)
39
+ result << _read_from_socket(nbytes - result.bytesize, buffer) while result.bytesize < nbytes
48
40
 
49
41
  result
50
42
  end
51
43
 
52
44
  def gets
53
- crlf = nil
54
-
55
- while (crlf = @buffer.index(CRLF)) == nil
56
- @buffer << _read_from_socket(1024)
45
+ while (crlf = @buffer.index(CRLF)).nil?
46
+ @buffer << _read_from_socket(16_384)
57
47
  end
58
48
 
59
49
  @buffer.slice!(0, crlf + CRLF.bytesize)
60
50
  end
61
51
 
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
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
100
67
  end
101
68
  end
102
-
103
- rescue EOFError
104
- raise Errno::ECONNRESET
105
69
  end
106
70
 
107
- def write(data)
108
- return super(data) unless @write_timeout
71
+ def write(buffer)
72
+ return super(buffer) unless @write_timeout
109
73
 
110
- length = data.bytesize
111
- total_count = 0
74
+ bytes_to_write = buffer.bytesize
75
+ total_bytes_written = 0
112
76
  loop do
113
- 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
90
+
91
+ if total_bytes_written >= bytes_to_write
92
+ return total_bytes_written
93
+ end
114
94
 
115
- total_count += count
116
- return total_count if total_count >= length
117
- data = data.byteslice(count..-1)
95
+ buffer = buffer.byteslice(bytes_written..-1)
96
+ end
118
97
  end
119
98
  end
120
99
  end
@@ -124,7 +103,6 @@ class Redis
124
103
  require "timeout"
125
104
 
126
105
  class TCPSocket < ::TCPSocket
127
-
128
106
  include SocketMixin
129
107
 
130
108
  def self.connect(host, port, timeout)
@@ -140,7 +118,6 @@ class Redis
140
118
  if defined?(::UNIXSocket)
141
119
 
142
120
  class UNIXSocket < ::UNIXSocket
143
-
144
121
  include SocketMixin
145
122
 
146
123
  def self.connect(path, timeout)
@@ -152,13 +129,12 @@ class Redis
152
129
  raise TimeoutError
153
130
  end
154
131
 
155
- # JRuby raises Errno::EAGAIN on #read_nonblock even when IO.select
132
+ # JRuby raises Errno::EAGAIN on #read_nonblock even when it
156
133
  # says it is readable (1.6.6, in both 1.8 and 1.9 mode).
157
134
  # Use the blocking #readpartial method instead.
158
135
 
159
136
  def _read_from_socket(nbytes)
160
137
  readpartial(nbytes)
161
-
162
138
  rescue EOFError
163
139
  raise Errno::ECONNRESET
164
140
  end
@@ -169,19 +145,16 @@ class Redis
169
145
  else
170
146
 
171
147
  class TCPSocket < ::Socket
172
-
173
148
  include SocketMixin
174
149
 
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])
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])
178
153
 
179
154
  begin
180
155
  sock.connect_nonblock(sockaddr)
181
156
  rescue Errno::EINPROGRESS
182
- if IO.select(nil, [sock], nil, timeout) == nil
183
- raise TimeoutError
184
- end
157
+ raise TimeoutError unless sock.wait_writable(timeout)
185
158
 
186
159
  begin
187
160
  sock.connect_nonblock(sockaddr)
@@ -220,14 +193,13 @@ class Redis
220
193
  return connect_addrinfo(ai, port, timeout)
221
194
  rescue SystemCallError
222
195
  # Raise if this was our last attempt.
223
- raise if addrinfo.length == i+1
196
+ raise if addrinfo.length == i + 1
224
197
  end
225
198
  end
226
199
  end
227
200
  end
228
201
 
229
202
  class UNIXSocket < ::Socket
230
-
231
203
  include SocketMixin
232
204
 
233
205
  def self.connect(path, timeout)
@@ -237,9 +209,7 @@ class Redis
237
209
  begin
238
210
  sock.connect_nonblock(sockaddr)
239
211
  rescue Errno::EINPROGRESS
240
- if IO.select(nil, [sock], nil, timeout) == nil
241
- raise TimeoutError
242
- end
212
+ raise TimeoutError unless sock.wait_writable(timeout)
243
213
 
244
214
  begin
245
215
  sock.connect_nonblock(sockaddr)
@@ -257,17 +227,58 @@ class Redis
257
227
  class SSLSocket < ::OpenSSL::SSL::SSLSocket
258
228
  include SocketMixin
259
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
+
260
242
  def self.connect(host, port, timeout, ssl_params)
261
243
  # Note: this is using Redis::Connection::TCPSocket
262
244
  tcp_sock = TCPSocket.connect(host, port, timeout)
263
245
 
264
246
  ctx = OpenSSL::SSL::SSLContext.new
265
- 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 || {})
266
250
 
267
251
  ssl_sock = new(tcp_sock, ctx)
268
252
  ssl_sock.hostname = host
269
- ssl_sock.connect
270
- ssl_sock.post_connection_check(host)
253
+
254
+ begin
255
+ # Initiate the socket connection in the background. If it doesn't fail
256
+ # immediately it will raise an IO::WaitWritable (Errno::EINPROGRESS)
257
+ # indicating the connection is in progress.
258
+ # Unlike waiting for a tcp socket to connect, you can't time out ssl socket
259
+ # connections during the connect phase properly, because IO.select only partially works.
260
+ # Instead, you have to retry.
261
+ ssl_sock.connect_nonblock
262
+ rescue Errno::EAGAIN, Errno::EWOULDBLOCK, IO::WaitReadable
263
+ if ssl_sock.wait_readable(timeout)
264
+ retry
265
+ else
266
+ raise TimeoutError
267
+ end
268
+ rescue IO::WaitWritable
269
+ if ssl_sock.wait_writable(timeout)
270
+ retry
271
+ else
272
+ raise TimeoutError
273
+ end
274
+ end
275
+
276
+ unless ctx.verify_mode == OpenSSL::SSL::VERIFY_NONE || (
277
+ ctx.respond_to?(:verify_hostname) &&
278
+ !ctx.verify_hostname
279
+ )
280
+ ssl_sock.post_connection_check(host)
281
+ end
271
282
 
272
283
  ssl_sock
273
284
  end
@@ -277,15 +288,16 @@ class Redis
277
288
  class Ruby
278
289
  include Redis::Connection::CommandHelper
279
290
 
280
- MINUS = "-".freeze
281
- PLUS = "+".freeze
282
- COLON = ":".freeze
283
- DOLLAR = "$".freeze
284
- ASTERISK = "*".freeze
291
+ MINUS = "-"
292
+ PLUS = "+"
293
+ COLON = ":"
294
+ DOLLAR = "$"
295
+ ASTERISK = "*"
285
296
 
286
297
  def self.connect(config)
287
298
  if config[:scheme] == "unix"
288
299
  raise ArgumentError, "SSL incompatible with unix sockets" if config[:ssl]
300
+
289
301
  sock = UNIXSocket.connect(config[:path], config[:connect_timeout])
290
302
  elsif config[:scheme] == "rediss" || config[:ssl]
291
303
  sock = SSLSocket.connect(config[:host], config[:port], config[:connect_timeout], config[:ssl_params])
@@ -294,13 +306,14 @@ class Redis
294
306
  end
295
307
 
296
308
  instance = new(sock)
297
- instance.timeout = config[:timeout]
309
+ instance.timeout = config[:read_timeout]
298
310
  instance.write_timeout = config[:write_timeout]
299
311
  instance.set_tcp_keepalive config[:tcp_keepalive]
312
+ instance.set_tcp_nodelay if sock.is_a? TCPSocket
300
313
  instance
301
314
  end
302
315
 
303
- 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 }
304
317
  def set_tcp_keepalive(keepalive)
305
318
  return unless keepalive.is_a?(Hash)
306
319
 
@@ -312,14 +325,13 @@ class Redis
312
325
 
313
326
  def get_tcp_keepalive
314
327
  {
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,
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
318
331
  }
319
332
  end
320
333
  else
321
- def set_tcp_keepalive(keepalive)
322
- end
334
+ def set_tcp_keepalive(keepalive); end
323
335
 
324
336
  def get_tcp_keepalive
325
337
  {
@@ -327,12 +339,21 @@ class Redis
327
339
  end
328
340
  end
329
341
 
342
+ # disables Nagle's Algorithm, prevents multiple round trips with MULTI
343
+ if %i[IPPROTO_TCP TCP_NODELAY].all? { |c| Socket.const_defined? c }
344
+ def set_tcp_nodelay
345
+ @sock.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
346
+ end
347
+ else
348
+ def set_tcp_nodelay; end
349
+ end
350
+
330
351
  def initialize(sock)
331
352
  @sock = sock
332
353
  end
333
354
 
334
355
  def connected?
335
- !! @sock
356
+ !!@sock
336
357
  end
337
358
 
338
359
  def disconnect
@@ -343,9 +364,7 @@ class Redis
343
364
  end
344
365
 
345
366
  def timeout=(timeout)
346
- if @sock.respond_to?(:timeout=)
347
- @sock.timeout = timeout
348
- end
367
+ @sock.timeout = timeout if @sock.respond_to?(:timeout=)
349
368
  end
350
369
 
351
370
  def write_timeout=(timeout)
@@ -360,7 +379,6 @@ class Redis
360
379
  line = @sock.gets
361
380
  reply_type = line.slice!(0, 1)
362
381
  format_reply(reply_type, line)
363
-
364
382
  rescue Errno::EAGAIN
365
383
  raise TimeoutError
366
384
  end
@@ -372,7 +390,7 @@ class Redis
372
390
  when COLON then format_integer_reply(line)
373
391
  when DOLLAR then format_bulk_reply(line)
374
392
  when ASTERISK then format_multi_bulk_reply(line)
375
- else raise ProtocolError.new(reply_type)
393
+ else raise ProtocolError, reply_type
376
394
  end
377
395
  end
378
396
 
@@ -391,6 +409,7 @@ class Redis
391
409
  def format_bulk_reply(line)
392
410
  bulklen = line.to_i
393
411
  return if bulklen == -1
412
+
394
413
  reply = encode(@sock.read(bulklen))
395
414
  @sock.read(2) # Discard CRLF.
396
415
  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
 
@@ -72,7 +77,15 @@ class Redis
72
77
 
73
78
  def self.connect(config)
74
79
  if config[:scheme] == "unix"
75
- conn = EventMachine.connect_unix_domain(config[:path], RedisClient)
80
+ begin
81
+ conn = EventMachine.connect_unix_domain(config[:path], RedisClient)
82
+ rescue RuntimeError => e
83
+ if e.message == "no connection"
84
+ raise Errno::ECONNREFUSED
85
+ else
86
+ raise e
87
+ end
88
+ end
76
89
  elsif config[:scheme] == "rediss" || config[:ssl]
77
90
  raise NotImplementedError, "SSL not supported by synchrony driver"
78
91
  else
@@ -97,7 +110,7 @@ class Redis
97
110
  end
98
111
 
99
112
  def connected?
100
- @connection && @connection.connected?
113
+ @connection&.connected?
101
114
  end
102
115
 
103
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